{"record":{"id":"5cb99077dd1ab872","repo":"risingwavelabs/risingwave","slug":"the-upstream-table-name-must-contain-database-name","errorCode":null,"errorMessage":"The upstream table name must contain database name prefix, e.g. 'database.table'","messagePattern":"The upstream table name must contain database name prefix, e\\.g\\. 'database\\.table'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/handler/create_table.rs","lineNumber":1009,"sourceCode":"/// - For MySQL/Postgres: Returns the original `external_table_name` unchanged.\nfn derive_with_options_for_cdc_table(\n    source_with_properties: &WithOptionsSecResolved,\n    external_table_name: String,\n) -> Result<(WithOptionsSecResolved, String)> {\n    use source::cdc::{MYSQL_CDC_CONNECTOR, POSTGRES_CDC_CONNECTOR, SQL_SERVER_CDC_CONNECTOR};\n    // we should remove the prefix from `full_table_name`\n    let source_database_name: &str = source_with_properties\n        .get(\"database.name\")\n        .ok_or_else(|| anyhow!(\"The source with properties does not contain 'database.name'\"))?\n        .as_str();\n    let mut with_options = source_with_properties.clone();\n    if let Some(connector) = source_with_properties.get(UPSTREAM_SOURCE_KEY) {\n        match connector.as_str() {\n            MYSQL_CDC_CONNECTOR => {\n                // MySQL doesn't allow '.' in database name and table name, so we can split the\n                // external table name by '.' to get the table name\n                let (db_name, table_name) = external_table_name.split_once('.').ok_or_else(|| {\n                    anyhow!(\"The upstream table name must contain database name prefix, e.g. 'database.table'\")\n                })?;\n                // We allow multiple database names in the source definition\n                if !source_database_name\n                    .split(',')\n                    .map(|s| s.trim())\n                    .any(|name| name == db_name)\n                {\n                    return Err(anyhow!(\n                        \"The database name `{}` in the FROM clause is not included in the database name `{}` in source definition\",\n                        db_name,\n                        source_database_name\n                    ).into());\n                }\n                with_options.insert(DATABASE_NAME_KEY.into(), db_name.into());\n                with_options.insert(TABLE_NAME_KEY.into(), table_name.into());\n                // Return original external_table_name unchanged for MySQL\n                return Ok((with_options, external_table_name));\n            }","sourceCodeStart":991,"sourceCodeEnd":1027,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/handler/create_table.rs#L991-L1027","documentation":"For MySQL CDC sources, the upstream table name in the FROM clause must carry a database prefix (`database.table`) because MySQL disallows `.` inside its database and table identifiers, so the name is split on the first `.`. If `external_table_name` has no `.`, `split_once` fails and this error is raised.","triggerScenarios":"`CREATE TABLE t (...) FROM mysql_src TABLE 'mytable'` (or unquoted table name without prefix) where the MySQL CDC source requires `'mydb.mytable'`; same check during `generate_stream_graph_for_replace_table`.","commonSituations":"Users following Postgres-style `schema.table` examples for MySQL, or omitting the prefix thinking the source's `database.name` suffices.","solutions":["Write the FROM clause table name as `'database.table'`, e.g. `FROM mysql_src TABLE 'mydb.orders'`.","Alternatively use `schema.table` format if supported for your connector, letting the source's `database.name` be validated against the prefix.","Check the exact name in MySQL (`SHOW TABLES` / `SELECT DATABASE()`) and mirror it in the FROM clause."],"exampleFix":"-- before\nCREATE TABLE t FROM mysql_src TABLE 'orders';\n-- after\nCREATE TABLE t FROM mysql_src TABLE 'mydb.orders';","handlingStrategy":"validation","validationCode":"fn valid_mysql_from_name(name: &str) -> bool {\n    name.contains('.') && name.split_once('.').map(|(db, t)| !db.is_empty() && !t.is_empty()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always quote and prefix MySQL CDC table names as 'database.table'","Never use schema.table (Postgres-style) syntax with mysql-cdc","Verify the identifier contains exactly one dot"],"tags":["rust","cdc","mysql","syntax"],"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"}