Docs/Streams/Features

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.

OptionDefaultEffect
tablestrueCreate tables on the target if they do not exist
indexestrueCreate indexes (primary keys, unique, secondary)
foreignKeystrueCreate foreign key constraints
checkConstraintstrueCreate 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 typePostgreSQL typeNotes
TINYINT(1)BOOLEAN
TINYINTSMALLINTSMALLSERIAL if auto_increment; CHECK constraint if unsigned
SMALLINTSMALLINTSMALLSERIAL if auto_increment; INTEGER if unsigned
MEDIUMINTINTEGERSERIAL if auto_increment; CHECK constraint if unsigned
INT / INTEGERINTEGERSERIAL if auto_increment; BIGINT if unsigned
BIGINTBIGINTBIGSERIAL if auto_increment; NUMERIC(20) if unsigned
SERIALSERIAL
BIGSERIALBIGSERIAL
SMALLSERIALSMALLSERIAL
FLOAT / REALREAL
DOUBLE / DOUBLE PRECISIONDOUBLE PRECISION
DECIMAL / NUMERICNUMERIC(p, s)Preserves precision and scale
BITBIT(n)Length extracted from column metadata; defaults to BIT(1)
YEARSMALLINT
CHARCHAR(n)Defaults to CHAR(1)
VARCHARVARCHAR(n)Defaults to VARCHAR(255)
TINYTEXTTEXT
TEXT / MEDIUMTEXT / LONGTEXTTEXT
DATETIMETIMESTAMP
TIMESTAMPTIMESTAMP
TIMESTAMPTZ / TIMESTAMP WITH TIME ZONETIMESTAMPTZ
TIMESTAMP WITHOUT TIME ZONETIMESTAMP
DATEDATE
TIMETIME
BOOLEAN / BOOLBOOLEAN
BINARY / VARBINARYBYTEA
TINYBLOB / BLOB / MEDIUMBLOB / LONGBLOBBYTEA
JSONJSONB
JSONBJSONB
ENUMTEXTWith CHECK constraint for allowed values
SETTEXT

Types not listed above map to TEXT as a fallback.

Data type mapping: PostgreSQL → MySQL

PostgreSQL typeMySQL typeNotes
SMALLINTSMALLINT
SMALLSERIALSMALLINTAuto_increment set
INTEGER / INTINT
SERIALINTAuto_increment set
BIGINTBIGINT
BIGSERIALBIGINTAuto_increment set
TINYINTTINYINT
MEDIUMINTINT
REAL / FLOATFLOAT
DOUBLE PRECISION / DOUBLEDOUBLE
NUMERIC / DECIMALDECIMAL(p, s)Preserves precision and scale
BIT / BIT VARYING / VARBITBIT(n) or VARBINARYBIT up to 64 → BIT(n); larger → VARBINARY or LONGBLOB; defaults to BIT(1)
CHARCHAR(n)Defaults to CHAR(1)
VARCHARVARCHAR(n)Defaults to VARCHAR(255)
TEXTLONGTEXT
MEDIUMTEXTMEDIUMTEXT
LONGTEXTLONGTEXT
TIMESTAMP / TIMESTAMP WITHOUT TIME ZONEDATETIME
TIMESTAMP WITH TIME ZONE / TIMESTAMPTZTIMESTAMP
DATETIMEDATETIME
DATEDATE
TIME / TIME WITHOUT TIME ZONETIME
YEARYEAR
BOOLEAN / BOOLTINYINT(1)
BYTEALONGBLOB
BLOBBLOB
TINYBLOBTINYBLOB
MEDIUMBLOBMEDIUMBLOB
LONGBLOBLONGBLOB
BINARYBINARY(n)Capped at 255; defaults to BINARY(1)
VARBINARYVARBINARY(n) or LONGBLOBVARBINARY up to 65535; larger → LONGBLOB; defaults to VARBINARY(255)
JSON / JSONBJSON
UUIDCHAR(36)
INETVARCHAR(45)
MACADDRVARCHAR(17)
TEXT / ARRAYJSON
USER-DEFINEDJSON, ENUM, or TEXTArrays → JSON; enums → ENUM with values; domain types → mapped recursively; fallback → TEXT
INTERVALVARCHAR(255)
ENUMTEXT
SETTEXT

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 typeDuckDB staging typeNotes
TINYINTTINYINT
SMALLINTSMALLINT
BIGINTBIGINT
INT / INTEGER / MEDIUMINTINTEGERAny type containing "INT" not matched above
DECIMAL / NUMERICDOUBLEPrecision/scale not preserved in file output
DOUBLE / FLOAT8DOUBLE
FLOAT / REALFLOAT
VARCHAR / TEXTVARCHAR(n) or VARCHARUses source length if valid and under 1M; otherwise unbounded
CHARCHAR(n) or VARCHARFalls back to VARCHAR if length not specified
TIMESTAMP / DATETIMETIMESTAMP
DATEDATE
TIMETIME
BOOLEAN / BOOLBOOLEAN
BLOB / BINARY / BYTEABLOB
JSON / JSONBJSON
UUIDUUID
ENUMVARCHAR

Types not listed above map to VARCHAR as a fallback.

Output format is determined by the target configuration:

FormatFile extensionDefault compression
CSV.csvuncompressed
JSONL.jsonluncompressed
Parquet.parquetzstd

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 to NULL. Boolean defaults 0/1 convert to false/true.
  • PostgreSQL → MySQL: PostgreSQL sequences (nextval()) are skipped. Boolean defaults true/false convert to 1/0. Type casts (::type) are removed.

Check constraint conversion

Check constraints are translated between SQL dialects:

  • PostgreSQL → MySQL: ANY(ARRAY[...]) converts to IN(...). PostgreSQL functions like jsonb_typeof map to MySQL equivalents like JSON_TYPE.
  • MySQL → PostgreSQL: MySQL functions like json_valid map to PostgreSQL equivalents like jsonb_typeof. Backtick identifiers convert to double quotes.