{"record":{"id":"ad690ecbdd994404","repo":"bytebase/bytebase","slug":"failed-to-parse-schema-ddl","errorCode":null,"errorMessage":"failed to parse schema DDL","messagePattern":"failed to parse schema DDL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/schema/mysql/get_database_metadata_omni.go","lineNumber":34,"sourceCode":"}\n\n// GetDatabaseMetadataOmni parses MySQL schema DDL text and returns database metadata\n// using the omni catalog. This replaces the ANTLR-based GetDatabaseMetadata.\nfunc GetDatabaseMetadataOmni(schemaText string) (*storepb.DatabaseSchemaMetadata, error) {\n\tif schemaText == \"\" {\n\t\treturn &storepb.DatabaseSchemaMetadata{}, nil\n\t}\n\n\tconst dbName = \"tmp\"\n\tc := catalog.New()\n\tinitSQL := fmt.Sprintf(\"SET foreign_key_checks = 0;\\nCREATE DATABASE IF NOT EXISTS `%s`;\\nUSE `%s`;\", dbName, dbName)\n\tif _, err := c.Exec(initSQL, nil); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to initialize catalog\")\n\t}\n\n\tresults, err := c.Exec(schemaText, &catalog.ExecOptions{ContinueOnError: true})\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to parse schema DDL\")\n\t}\n\n\t// Check for hard errors (not per-statement errors).\n\tfor _, r := range results {\n\t\tif r.Error != nil {\n\t\t\treturn nil, errors.Wrapf(r.Error, \"failed to execute schema DDL\")\n\t\t}\n\t}\n\n\tproto := catalogToProto(c, dbName)\n\treturn proto, nil\n}\n","sourceCodeStart":16,"sourceCodeEnd":47,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/schema/mysql/get_database_metadata_omni.go#L16-L47","documentation":"After initializing the catalog, GetDatabaseMetadataOmni executes the whole schema DDL text through the embedded omni MySQL catalog with ContinueOnError. If the batch itself fails (e.g. the SQL cannot be parsed at all), the error is wrapped as 'failed to parse schema DDL'. This indicates the input is not valid MySQL DDL for the embedded parser.","triggerScenarios":"Calling GetDatabaseMetadataOmni with schemaText containing syntax the omni parser rejects, non-DDL statements, or malformed multi-statement input.","commonSituations":"Schema text produced by another tool with MySQL-incompatible syntax; dialect drift between the generator and the omni parser; truncated or concatenated DDL files.","solutions":["Unwrap the error to find the offending statement and parser message.","Validate the schemaText with mysql client or lint it as MySQL DDL before passing it in.","Fix or regenerate the DDL so it is standard MySQL CREATE TABLE/VIEW/etc. syntax.","If specific statements legitimately fail, rely on the per-statement results path (ContinueOnError) rather than the batch error and inspect results for r.Error."],"exampleFix":"// before\nproto, err := GetDatabaseMetadataOmni(ctx, rawDDL) // rawDDL contains dialect-specific syntax\n// after\nvalidated, err := lintAndNormalizeMySQLDDL(rawDDL)\nif err != nil {\n    return nil, err\n}\nproto, err := GetDatabaseMetadataOmni(ctx, validated)","handlingStrategy":"validation","validationCode":"if err := validateMySQLDDL(schemaText); err != nil {\n    return nil, fmt.Errorf(\"schemaText is not valid MySQL DDL: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to parse schema DDL\") {\n    return nil, fmt.Errorf(\"input schema rejected by parser: %w\", err)\n}","preventionTips":["Generate schema text only from tools emitting standard MySQL DDL","Lint the DDL (mysql --force dry run or a parser) before calling GetDatabaseMetadataOmni","Watch for dialect drift when the DDL producer and the omni parser versions diverge"],"tags":["mysql","ddl","parser","omni"],"backgroundTag":"sql-query-failed","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}