{"record":{"id":"a8c40f62309f6bc1","repo":"risingwavelabs/risingwave","slug":"failed-to-parse-mysql-default-value-expression-on","errorCode":null,"errorMessage":"failed to parse mysql default value expression, only constant is supported","messagePattern":"failed to parse mysql default value expression, only constant is supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/source/cdc/external/mysql.rs","lineNumber":250,"sourceCode":"                Some(ScalarImpl::from(val.to_string()))\n            }\n            _ => bail!(\"unexpected default value type for integer\"),\n        },\n        ColumnDefault::Real(val) => match data_type {\n            DataType::Float32 => Some(ScalarImpl::Float32(F32::from(val as f32))),\n            DataType::Float64 => Some(ScalarImpl::Float64(val.into())),\n            DataType::Decimal => Some(ScalarImpl::Decimal(\n                Decimal::try_from(val).context(\"failed to convert default value to decimal\")?,\n            )),\n            _ => bail!(\"unexpected default value type for real\"),\n        },\n        ColumnDefault::String(mut val) => {\n            // mysql timestamp is mapped to timestamptz, we use UTC timezone to\n            // interpret its value\n            if data_type == &DataType::Timestamptz {\n                val = timestamp_val_to_timestamptz(val.as_str())?;\n            }\n            Some(ScalarImpl::from_text(val.as_str(), data_type).map_err(|e| anyhow!(e)).context(\n                \"failed to parse mysql default value expression, only constant is supported\",\n            )?)\n        }\n        ColumnDefault::CurrentTimestamp | ColumnDefault::CustomExpr(_) => {\n            bail!(\"MySQL CURRENT_TIMESTAMP and custom expression default value not supported\")\n        }\n    };\n    Ok(datum)\n}\n\npub fn timestamp_val_to_timestamptz(value_text: &str) -> ConnectorResult<String> {\n    let format = \"%Y-%m-%d %H:%M:%S\";\n    let naive_datetime = NaiveDateTime::parse_from_str(value_text, format)\n        .map_err(|err| anyhow!(\"failed to parse mysql timestamp value\").context(err))?;\n    let postgres_timestamptz: DateTime<chrono::Utc> =\n        DateTime::<chrono::Utc>::from_naive_utc_and_offset(naive_datetime, chrono::Utc);\n    Ok(postgres_timestamptz\n        .format(\"%Y-%m-%d %H:%M:%S%:z\")","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/cdc/external/mysql.rs#L232-L268","documentation":"RisingWave CDC schema discovery supports only constant (literal) MySQL default values. When the default is a string/expression form, the connector tries to parse its text into the RW type via from_text; any parse failure surfaces as this context-wrapped error. It effectively means 'the default value is not a plain constant we can represent'.","triggerScenarios":"A MySQL column whose DEFAULT is a non-literal expression (e.g. DEFAULT (NOW()), DEFAULT (UUID()), computed expressions) that fails from_text parsing into the target type.","commonSituations":"MySQL 8.0 expression defaults; defaults with functions or casts; string defaults containing formatting that doesn't fit the RW type (e.g. bad date literals).","solutions":["Replace the MySQL column default with a constant literal compatible with the column type.","If the value must be dynamic, drop the default in MySQL and handle it in the producer application.","Check the literal text parses for the RW type (e.g. valid timestamp format for timestamp columns)."],"exampleFix":"// before (MySQL)\nCREATE TABLE t (id INT, created TIMESTAMP DEFAULT (NOW()));\n// after\nCREATE TABLE t (id INT, created TIMESTAMP DEFAULT '2024-01-01 00:00:00');","handlingStrategy":"validation","validationCode":"-- find non-literal (expression) defaults, MySQL 8+\nSELECT COLUMN_NAME, COLUMN_DEFAULT, EXTRA FROM information_schema.COLUMNS\nWHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='t'\n  AND COLUMN_DEFAULT IS NOT NULL\n  AND (COLUMN_DEFAULT LIKE '%(%' OR EXTRA LIKE '%DEFAULT_GENERATED%');","typeGuard":"function isConstantDefault(d) {\n  return typeof d === \"string\" && !d.includes(\"(\") && !/^current_/i.test(d.trim());\n}","tryCatchPattern":"try { await createCdcTable('t'); } catch (e) { if (String(e).includes('only constant is supported')) { /* replace expression default with a literal in MySQL, retry */ } else throw e; }","preventionTips":["Avoid MySQL 8.0 expression/function defaults on CDC-replicated tables","Scan COLUMN_DEFAULT for parentheses or function names before onboarding","Keep defaults as simple literals"],"tags":["cdc","mysql","default-value","parse"],"backgroundTag":"invalid-argument-format","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}