{"record":{"id":"c836ca53780007d9","repo":"risingwavelabs/risingwave","slug":"mysql-current-timestamp-and-custom-expression-defa","errorCode":null,"errorMessage":"MySQL CURRENT_TIMESTAMP and custom expression default value not supported","messagePattern":"MySQL CURRENT_TIMESTAMP and custom expression default value not supported","errorType":"validation","errorClass":"ConnectorError","httpStatus":null,"severity":"error","filePath":"src/connector/src/source/cdc/external/mysql.rs","lineNumber":255,"sourceCode":"            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\")\n        .to_string())\n}\n\npub fn type_name_to_mysql_type(ty_name: &str) -> Option<ColumnType> {\n    // Debezium schema change message may include extra qualifiers, e.g. `BIGINT UNSIGNED`,","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/cdc/external/mysql.rs#L237-L273","documentation":"The MySQL CDC connector cannot represent CURRENT_TIMESTAMP defaults or arbitrary custom expression defaults, because RisingWave must replay the exact default value. derive_default_value explicitly bails when it encounters ColumnDefault::CurrentTimestamp or ColumnDefault::CustomExpr.","triggerScenarios":"Creating a CDC table whose MySQL column has DEFAULT CURRENT_TIMESTAMP (or ON UPDATE CURRENT_TIMESTAMP captured as such), or any parenthesized expression default.","commonSituations":"Very common audit columns (created_at/updated_at with CURRENT_TIMESTAMP); MySQL 8.0 expression defaults; tables auto-generated by ORMs.","solutions":["Remove the CURRENT_TIMESTAMP/expression default from the MySQL column, or replace it with a constant literal.","Exclude the column from the CDC table definition if it is not needed in RW.","Handle timestamping on the RisingWave side (e.g. compute at insert time) instead of relying on MySQL defaults."],"exampleFix":"// before (MySQL)\nCREATE TABLE t (created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);\n// after\nCREATE TABLE t (created_at TIMESTAMP NULL DEFAULT NULL);","handlingStrategy":"validation","validationCode":"SELECT COLUMN_NAME FROM information_schema.COLUMNS\nWHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='t'\n  AND (UPPER(COLUMN_DEFAULT) LIKE 'CURRENT_TIMESTAMP%' OR UPPER(COLUMN_DEFAULT) = 'NOW()');","typeGuard":"function hasCurrentTimestampDefault(col) {\n  return /^current_timestamp(\\(\\d*\\))?$/i.test(String(col.COLUMN_DEFAULT).trim());\n}","tryCatchPattern":"try { await createCdcTable('t'); } catch (e) { if (String(e).includes('CURRENT_TIMESTAMP and custom expression default value not supported')) { /* drop/replace the default, then retry */ } else throw e; }","preventionTips":["Avoid DEFAULT CURRENT_TIMESTAMP / ON UPDATE CURRENT_TIMESTAMP columns in CDC sources","Let the application or RisingWave set timestamps instead","Audit information_schema.COLUMNS for CURRENT_TIMESTAMP defaults before onboarding"],"tags":["cdc","mysql","default-value","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}