# MySQL schema fidelity The MySQL reader/writer preserves the table-schema features below. It generates DDL for **new tables in existing databases**, not migrations or data copies. MySQL 8.4 / InnoDB is exercised by the live suite. The reader uses MySQL 8.0.23+ metadata (including functional indexes, checks, spatial metadata, and invisible columns); older MySQL versions and the `mariadb` alias are not certified by this suite and may return explicit metadata-query errors. ## Conversion diagnostics MySQL output warns on stderr when it encounters known unsupported features. Add `--strict-conversion` to reject these conversions before opening an output file or connecting to an output database: ```bash relspec convert --from mysql --from-conn "$MYSQL_DSN" \ --to mysql --to-path schema.sql --strict-conversion relspec convert --from json --from-path schema.json \ --to mysql --to-path schema.sql --strict-conversion --dry-run ``` The flag also applies to MySQL output from `batch`, `split`, and schema jobs. Jobs can set `options.strict_conversion: true`. Library callers use `writers.WriterOptions.StrictConversion`; `Warning func(string)` collects non-strict diagnostics instead of printing them. `mysql.Writer.Statements` performs the same preflight without opening a destination and returns structured SQL statements suitable for execution without splitting on semicolons. Strict conversion currently covers **MySQL output**. It is not a general losslessness check for other writers or a validator of arbitrary SQL fragments. Warnings identify the object and omitted or changed feature. Inspect them before using non-strict output; unsupported index types are omitted, while a partial index's predicate and INCLUDE columns cannot be represented in MySQL. ## MySQL capability matrix | Feature | Reader → model | Model → MySQL DDL | | --- | --- | --- | | Ordered columns, nullability, primary/composite keys | Preserved | Preserved | | Unique/composite keys | Preserved, including backing indexes | Preserved once; no duplicate unique index | | Foreign/composite keys and DELETE/UPDATE actions | Preserved | Added after all tables, allowing forward references/cycles | | CHECK and NOT ENFORCED CHECK | Preserved | Preserved | | BTREE, FULLTEXT, SPATIAL indexes | Preserved | Emitted; engine restrictions still apply | | Expression/prefix/descending/invisible index parts | Preserved in `Index.KeyParts` and metadata | Preserved | | HASH indexes | Preserved | Engine-dependent; incompatible engine produces a diagnostic | | Integer unsignedness; mediumint; enum/set; binary/blob/text variants | Canonical type plus native declaration | Native declaration preserved | | Length, numeric precision/scale, fractional seconds | Typed dimensions plus native declaration | Preserved; canonical dimensions also supported | | Defaults, including SQL expressions, bit/binary literals and multiline text | Values plus native SQL spelling from SHOW CREATE | Preserved | | Auto-increment and current next value | Preserved | Preserved | | Stored/virtual generated columns, ON UPDATE, invisible columns | Preserved | Preserved | | Engine, table/column collation, charset and comments | Preserved | Preserved | | Views, triggers, routines, events, partitioned tables | Names recorded in `mysql_unsupported` | Diagnostic; bodies/partition definitions are not emitted | | Nonempty table CREATE_OPTIONS; native parser/storage/engine attributes; spatial SRID | Recorded as unsupported attributes | Diagnostic; not emitted | | Partial/INCLUDE indexes, unsupported index methods | Retained when supplied in the model | Diagnostic | | Deferrable constraints, identity semantics, timestamptz, jsonb storage | Retained when supplied in the model | Diagnostic for unsupported/different semantics | | Standalone sequences/enums/domains, ownership/permissions, scripts and dialect directives | Retained when supplied in the model | Diagnostic; not emitted | | Data, grants, users, server/plugin configuration | Outside the reader's schema contract | Outside the writer's contract | Diagnostics depend on the objects visible to the connection account. They cover known modeled/discovered features, not every engine/plugin extension. The server still validates SQL expressions, engine rules, and references at execution time. For example, source and target engines must support the constraints requested. ## Preservation across intermediate formats | Path | Scope | | --- | --- | | MySQL → model → MySQL | Live-tested for the features above on MySQL 8.4 / InnoDB | | MySQL → JSON → model → MySQL | Live-tested; preserves typed index parts and MySQL metadata | | MySQL → YAML → model → MySQL | YAML serializes the same fields/metadata; covered by the live round-trip test | | Other source/target formats | Their own mappings apply; MySQL-specific metadata and semantics are not certified to survive | Native declarations and defaults are stored in column metadata as `mysql_type` and `mysql_default_sql`. Reader-generated signatures (`mysql_type_signature`, `mysql_default_value`) prevent these spellings from silently overriding edited types/dimensions/defaults. Editing canonical dimensions invalidates the native type signature, produces a diagnostic, and uses the canonical mapping instead. For a binary default, the logical default is its SQL hex/literal spelling so it survives serialization without invalid UTF-8. Other metadata includes `mysql_charset`, `mysql_generation_storage`, `mysql_default_expression`, `mysql_on_update`, `mysql_invisible`, table `mysql_engine` / `mysql_collation` / `mysql_auto_increment`, index `mysql_visible`, and check `mysql_enforced`. Unknown `mysql_*` metadata produces a diagnostic. For a manually authored expression default, set `mysql_default_expression: true`; otherwise strings are literal values. `Index.KeyParts` is authoritative when present; `Index.Columns` remains the compatibility representation for simple indexes. Raw native type declarations, default SQL, generation/check/index expressions, and ON UPDATE expressions are executable SQL input. Lowercasing changes names and structured index parts but leaves expressions untouched; update references inside raw SQL yourself when using `--lowercase`. ## Applying the output Create the destination database/schema first. Qualified names are preserved, including foreign-key target schemas. Adjust them explicitly when restoring to a different database. Output assumes standard MySQL backslash escaping; `NO_BACKSLASH_ESCAPES` or `ANSI_QUOTES` on the source produces a conversion diagnostic, and live execution refuses these target modes before DDL. File consumers must use the same supported mode. Other SQL-mode incompatibilities surface as server errors. `CREATE TABLE IF NOT EXISTS` does not reconcile existing definitions. Foreign keys use `ALTER TABLE ADD CONSTRAINT` and therefore repeated application can fail on existing constraints. This is creation DDL, not a rerunnable migration. Live execution stops on the first SQL error by default. Explicit `ContinueOnError` attempts later statements and still returns an error if any fail. MySQL DDL implicitly commits; `AtomicExecution` is rejected. PostgreSQL's shared execution-report support is not yet implemented for this writer. ## Verification ```bash ./tests/dbtest/dbtest.sh test mysql # Or use your own disposable database: RELSPEC_TEST_MYSQL_CONN="$MYSQL_DSN" go test -mod=vendor ./pkg/readers/mysql ./pkg/writers/mysql ``` The live tests compare MySQL's `SHOW CREATE TABLE` definitions, normalizing only temporary target-name suffixes and nonsemantic ordinary-index display order. They re-read the target, exercise constraint enforcement/default values, and verify unsupported objects produce warnings or strict failures without touching an existing output file. Test fixtures are removed after each run. Metadata references: [COLUMNS](https://dev.mysql.com/doc/refman/8.4/en/information-schema-columns-table.html), [STATISTICS](https://dev.mysql.com/doc/refman/8.4/en/information-schema-statistics-table.html), [TABLE_CONSTRAINTS](https://dev.mysql.com/doc/refman/8.4/en/information-schema-table-constraints-table.html), and [REFERENTIAL_CONSTRAINTS](https://dev.mysql.com/doc/refman/8.4/en/information-schema-referential-constraints-table.html).