Table Structure Conversion
DBConvert Streams automatically converts table structure between source and target when they use different engines or formats. This includes data types, indexes, foreign keys, and check constraints.
Structure conversion applies to both Load and CDC modes.
Supported conversion paths
Database ↔ database
- MySQL → PostgreSQL
- PostgreSQL → MySQL
- MariaDB → PostgreSQL
- PostgreSQL → MariaDB
Files / S3 → database
- CSV → MySQL / PostgreSQL
- JSON / JSONL → MySQL / PostgreSQL
- Parquet → MySQL / PostgreSQL
Database → files / S3
- MySQL / PostgreSQL → CSV, JSONL, or Parquet files (local or S3)
Structure options
Structure creation is controlled per-stream via the structureOptions object in the target spec. All options are booleans and default to true.
| Option | Default | Effect |
|---|---|---|
tables | true | Create tables on the target if they do not exist |
indexes | true | Create indexes (primary keys, unique, secondary) |
foreignKeys | true | Create foreign key constraints |
checkConstraints | true | Create check constraints |
Set an option to false to skip that structure type. For example, disabling indexes on large tables can speed up the initial load — you can create them manually afterward.
API example
{
"target": {
"id": "conn_TARGET_ID",
"spec": {
"db": {
"database": "target_db",
"structureOptions": {
"tables": true,
"indexes": false,
"foreignKeys": false,
"checkConstraints": true
}
}
}
}
}
In the UI, the stream wizard Structure & Data step exposes these as checkboxes under the advanced section.
Data type mapping: MySQL → PostgreSQL
| MySQL type | PostgreSQL type | Notes |
|---|---|---|
| TINYINT(1) | BOOLEAN | |
| TINYINT | SMALLINT | SMALLSERIAL if auto_increment; CHECK constraint if unsigned |
| SMALLINT | SMALLINT | SMALLSERIAL if auto_increment; INTEGER if unsigned |
| MEDIUMINT | INTEGER | SERIAL if auto_increment; CHECK constraint if unsigned |
| INT / INTEGER | INTEGER | SERIAL if auto_increment; BIGINT if unsigned |
| BIGINT | BIGINT | BIGSERIAL if auto_increment; NUMERIC(20) if unsigned |
| SERIAL | SERIAL | |
| BIGSERIAL | BIGSERIAL | |
| SMALLSERIAL | SMALLSERIAL | |
| FLOAT / REAL | REAL | |
| DOUBLE / DOUBLE PRECISION | DOUBLE PRECISION | |
| DECIMAL / NUMERIC | NUMERIC(p, s) | Preserves precision and scale |
| BIT | BIT(n) | Length extracted from column metadata; defaults to BIT(1) |
| YEAR | SMALLINT | |
| CHAR | CHAR(n) | Defaults to CHAR(1) |
| VARCHAR | VARCHAR(n) | Defaults to VARCHAR(255) |
| TINYTEXT | TEXT | |
| TEXT / MEDIUMTEXT / LONGTEXT | TEXT | |
| DATETIME | TIMESTAMP | |
| TIMESTAMP | TIMESTAMP | |
| TIMESTAMPTZ / TIMESTAMP WITH TIME ZONE | TIMESTAMPTZ | |
| TIMESTAMP WITHOUT TIME ZONE | TIMESTAMP | |
| DATE | DATE | |
| TIME | TIME | |
| BOOLEAN / BOOL | BOOLEAN | |
| BINARY / VARBINARY | BYTEA | |
| TINYBLOB / BLOB / MEDIUMBLOB / LONGBLOB | BYTEA | |
| JSON | JSONB | |
| JSONB | JSONB | |
| ENUM | TEXT | With CHECK constraint for allowed values |
| SET | TEXT |
Types not listed above map to TEXT as a fallback.
Data type mapping: PostgreSQL → MySQL
| PostgreSQL type | MySQL type | Notes |
|---|---|---|
| SMALLINT | SMALLINT | |
| SMALLSERIAL | SMALLINT | Auto_increment set |
| INTEGER / INT | INT | |
| SERIAL | INT | Auto_increment set |
| BIGINT | BIGINT | |
| BIGSERIAL | BIGINT | Auto_increment set |
| TINYINT | TINYINT | |
| MEDIUMINT | INT | |
| REAL / FLOAT | FLOAT | |
| DOUBLE PRECISION / DOUBLE | DOUBLE | |
| NUMERIC / DECIMAL | DECIMAL(p, s) | Preserves precision and scale |
| BIT / BIT VARYING / VARBIT | BIT(n) or VARBINARY | BIT up to 64 → BIT(n); larger → VARBINARY or LONGBLOB; defaults to BIT(1) |
| CHAR | CHAR(n) | Defaults to CHAR(1) |
| VARCHAR | VARCHAR(n) | Defaults to VARCHAR(255) |
| TEXT | LONGTEXT | |
| MEDIUMTEXT | MEDIUMTEXT | |
| LONGTEXT | LONGTEXT | |
| TIMESTAMP / TIMESTAMP WITHOUT TIME ZONE | DATETIME | |
| TIMESTAMP WITH TIME ZONE / TIMESTAMPTZ | TIMESTAMP | |
| DATETIME | DATETIME | |
| DATE | DATE | |
| TIME / TIME WITHOUT TIME ZONE | TIME | |
| YEAR | YEAR | |
| BOOLEAN / BOOL | TINYINT(1) | |
| BYTEA | LONGBLOB | |
| BLOB | BLOB | |
| TINYBLOB | TINYBLOB | |
| MEDIUMBLOB | MEDIUMBLOB | |
| LONGBLOB | LONGBLOB | |
| BINARY | BINARY(n) | Capped at 255; defaults to BINARY(1) |
| VARBINARY | VARBINARY(n) or LONGBLOB | VARBINARY up to 65535; larger → LONGBLOB; defaults to VARBINARY(255) |
| JSON / JSONB | JSON | |
| UUID | CHAR(36) | |
| INET | VARCHAR(45) | |
| MACADDR | VARCHAR(17) | |
| TEXT / ARRAY | JSON | |
| USER-DEFINED | JSON, ENUM, or TEXT | Arrays → JSON; enums → ENUM with values; domain types → mapped recursively; fallback → TEXT |
| INTERVAL | VARCHAR(255) | |
| ENUM | TEXT | |
| SET | TEXT |
Types not listed above map to TEXT as a fallback.
File source → database target
When the source is a local file or S3 object, DBConvert Streams uses DuckDB to infer the schema:
- Parquet: schema is read from the file metadata (column names, types, nullability)
- CSV:
read_csv_auto()infers column names from headers and types from sampled values - JSON / JSONL:
read_json_auto()infers structure from the document fields
The inferred types use standard SQL names (VARCHAR, INTEGER, TIMESTAMP, etc.) and flow through the same MySQL or PostgreSQL type mapper described above. For example, a Parquet column typed as BIGINT maps to BIGINT on both MySQL and PostgreSQL targets through the normal conversion path.
Database source → file target
When the target is a local file directory or S3 bucket, DBConvert Streams maps database types to DuckDB staging types for export:
| Database type | DuckDB staging type | Notes |
|---|---|---|
| TINYINT | TINYINT | |
| SMALLINT | SMALLINT | |
| BIGINT | BIGINT | |
| INT / INTEGER / MEDIUMINT | INTEGER | Any type containing "INT" not matched above |
| DECIMAL / NUMERIC | DOUBLE | Precision/scale not preserved in file output |
| DOUBLE / FLOAT8 | DOUBLE | |
| FLOAT / REAL | FLOAT | |
| VARCHAR / TEXT | VARCHAR(n) or VARCHAR | Uses source length if valid and under 1M; otherwise unbounded |
| CHAR | CHAR(n) or VARCHAR | Falls back to VARCHAR if length not specified |
| TIMESTAMP / DATETIME | TIMESTAMP | |
| DATE | DATE | |
| TIME | TIME | |
| BOOLEAN / BOOL | BOOLEAN | |
| BLOB / BINARY / BYTEA | BLOB | |
| JSON / JSONB | JSON | |
| UUID | UUID | |
| ENUM | VARCHAR |
Types not listed above map to VARCHAR as a fallback.
Output format is determined by the target configuration:
| Format | File extension | Default compression |
|---|---|---|
| CSV | .csv | uncompressed |
| JSONL | .jsonl | uncompressed |
| Parquet | .parquet | zstd |
All formats also support gzip and zstd compression. Parquet additionally supports snappy.
Default value conversion
DBConvert Streams also converts default values between database engines:
- MySQL → PostgreSQL: MySQL zero dates (
0000-00-00) convert toNULL. Boolean defaults0/1convert tofalse/true. - PostgreSQL → MySQL: PostgreSQL sequences (
nextval()) are skipped. Boolean defaultstrue/falseconvert to1/0. Type casts (::type) are removed.
Check constraint conversion
Check constraints are translated between SQL dialects:
- PostgreSQL → MySQL:
ANY(ARRAY[...])converts toIN(...). PostgreSQL functions likejsonb_typeofmap to MySQL equivalents likeJSON_TYPE. - MySQL → PostgreSQL: MySQL functions like
json_validmap to PostgreSQL equivalents likejsonb_typeof. Backtick identifiers convert to double quotes.