YunaiV/yudao-cloud · error · NotImplementedError

f"未支持的类型: '{col['type']}' (列: {name}, 表: {ddl['table_name']}

Error message

f"未支持的类型: '{col['type']}' (列: {name}, 表: {ddl['table_name']})"

What it means

Raised inside gen_create -> _generate_column in sql/tools/convertor.py when translate_type(type, size) returns None for the column's MySQL type. Each convertor's translate_type is a whitelist of if-comparisons (varchar, int, bigint, tinyint, datetime, json, double, bit, text, blob, decimal, ...); any MySQL type not on the list falls off the end, returning None, and _generate_column raises NotImplementedError naming the type, column, and table. It means the DDL convertor simply has no mapping rule for that column type yet.

Source

Thrown at sql/tools/convertor.py:447

        if type in ("blob", "mediumblob", "longblob"):
            return "bytea"
        if type == "decimal":
            return (
                f"numeric({','.join(str(s) for s in size)})" if size and len(size) else "numeric"
            )

    def gen_create(self, ddl: Dict) -> str:
        """生成 create"""

        def _generate_column(col):
            name = col["name"].lower()
            if name == "deleted":
                return "deleted int2 NOT NULL DEFAULT 0"

            type = col["type"].lower()
            full_type = self.translate_type(type, col["size"])
            if full_type is None:
                raise NotImplementedError(
                    f"未支持的类型: '{col['type']}' (列: {name}, 表: {ddl['table_name']})"
                )
            nullable = "NULL" if col["nullable"] else "NOT NULL"
            default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
            return f"{self.escape_column_name(name)} {full_type} {nullable} {default}"

        table_name = ddl["table_name"].lower()
        columns = [f"{_generate_column(col).strip()}" for col in ddl["columns"]]
        filed_def_list = ",\n  ".join(columns)
        script = f"""-- ----------------------------
-- Table structure for {table_name}
-- ----------------------------
DROP TABLE IF EXISTS {table_name};
CREATE TABLE {table_name} (
    {filed_def_list}
);"""

        return script

View on GitHub (pinned to 477be9dd49)

Solutions

  1. Read the message: it names the exact column type, column, and table — open the source DDL and confirm the raw type string (the code compares type.lower() against exact literals).
  2. Add a mapping branch to translate_type in the convertor class you are using (line 402 area for the PostgreSQL-family convertor) — e.g. `if type == "float": return "float4"`, `if type == "enum": return "varchar(255)"`, `if type == "char": return f"char({size})"`.
  3. If the type is irrelevant (audit/legacy column), strip or edit that column from the input SQL dump and re-run.
  4. For one-off conversions, pre-normalize the DDL with sed to rewrite the unsupported type to a supported one before feeding it to the convertor.

Example fix

# before — translate_type has no branch for 'float'/'enum', so it returns None and gen_create raises NotImplementedError

# after — add branches to translate_type (sql/tools/convertor.py, PostgreSQL-family convertor)
if type == "float":
    return "float4"
if type == "enum":
    return "varchar(255)"
if type == "char":
    return f"char({size})" if size else "char"
Defensive patterns

Strategy: type-guard

Validate before calling

SUPPORTED_TYPES = {
    "varchar", "int", "int unsigned", "int unsigned zerofill", "bigint", "bigint unsigned",
    "tinyint", "smallint", "tinyint unsigned", "datetime", "timestamp null", "date",
    "json", "double", "timestamp", "bit", "text", "longtext", "blob", "mediumblob",
    "longblob", "decimal",
}

# scan the parsed DDL before generating
def check_columns(ddl):
    bad = [c for c in ddl["columns"] if c["type"].lower() not in SUPPORTED_TYPES and c["name"].lower() != "deleted"]
    if bad:
        raise ValueError(f"Unsupported types in table {ddl['table_name']}: {[(c['name'], c['type']) for c in bad]}")

Type guard

def is_supported_type(col: Dict) -> bool:
    """True if convertor.translate_type maps this column type (never returns None)."""
    if col["name"].lower() == "deleted":
        return True
    return convertor.translate_type(col["type"].lower(), col.get("size")) is not None

Try / catch

try:
    script = convertor.gen_create(ddl)
except NotImplementedError as e:
    # e.message names the type, column, and table: add a mapping branch to
    # translate_type, or normalize/skip that column, then re-run
    log.warning("skipping table %s: %s", ddl["table_name"], e)
    # decide: fix the mapping (preferred) or skip the table and report it

Prevention

When it happens

Trigger: Running the convertor CLI on a MySQL DDL dump that contains a column type not in the whitelist, e.g. ENUM('a','b'), SET, FLOAT, MEDIUMINT, CHAR(n), YEAR, GEOMETRY, VARBINARY, or a vendor-specific type. The error fires per-table while generating CREATE TABLE statements, and includes the offending column name and table name.

Common situations: Converting a hand-written or legacy schema that uses ENUM/SET instead of lookup tables; converting MySQL 8 dumps with newer types; a type spelled differently in the dump than the whitelist expects (the comparison is exact after .lower()); processing third-party application schemas (WordPress, etc.) with unusual types.

Related errors


AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14). Data as JSON: /api/errors/490b877415327b8a. Report an issue: GitHub.