(databaseName string, n *ast.UpdateStmt, fullSQL string, dbMetadata *model.DatabaseMetadata, isCaseSensitive bool)
| 235 | } |
| 236 | |
| 237 | func extractTablesFromUpdate(databaseName string, n *ast.UpdateStmt, fullSQL string, dbMetadata *model.DatabaseMetadata, isCaseSensitive bool) ([]statementInfo, error) { |
| 238 | cteNames := collectCTENames(fullSQL, n.Loc) |
| 239 | stmtText := extractStatementText(fullSQL, n.Loc) |
| 240 | |
| 241 | singleTables := collectSingleTables(databaseName, cteNames, n.Tables, isCaseSensitive) |
| 242 | |
| 243 | // Determine which tables the SET clause writes, via column table prefixes. |
| 244 | updatedTables := make(map[string]bool) |
| 245 | var unqualifiedColumns []string |
| 246 | for _, assign := range n.SetList { |
| 247 | if assign == nil || assign.Column == nil { |
| 248 | continue |
| 249 | } |
| 250 | table := assign.Column.Table |
| 251 | if table == "" { |
| 252 | updatedTables[""] = true |
| 253 | unqualifiedColumns = append(unqualifiedColumns, assign.Column.Column) |
| 254 | continue |
| 255 | } |
| 256 | // Look up the qualifier case-insensitively (TiDB default): the alias/name |
| 257 | // resolves regardless of the case used in the SET clause. |
| 258 | key := identifierKey(table, isCaseSensitive) |
| 259 | // Skip only if the qualifier resolves to a CTE reference in the FROM — a |
| 260 | // CTE can't be a mutation target. A real table aliased with a CTE's name |
| 261 | // (its resolved table is real) is still an update target. |
| 262 | if ref, ok := singleTables[key]; ok && isCTERef(cteNames, ref) { |
| 263 | continue |
| 264 | } |
| 265 | updatedTables[key] = true |
| 266 | } |
| 267 | |
| 268 | // Resolve unqualified SET columns to their owning table(s) via metadata. |
| 269 | // Exclude CTE refs from the candidates: a CTE can't be a mutation target, |
| 270 | // and resolveUnqualifiedColumns' metadata-unavailable/unresolved fallback |
| 271 | // would otherwise mark every candidate (CTEs included). |
| 272 | if updatedTables[""] { |
| 273 | delete(updatedTables, "") |
| 274 | candidates := make(map[string]*TableReference, len(singleTables)) |
| 275 | for key, ref := range singleTables { |
| 276 | if isCTERef(cteNames, ref) { |
| 277 | continue |
| 278 | } |
| 279 | candidates[key] = ref |
| 280 | } |
| 281 | for t := range resolveUnqualifiedColumns(unqualifiedColumns, candidates, dbMetadata) { |
| 282 | updatedTables[t] = true |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | // Single-table UPDATE: no explicit qualification needed. |
| 287 | if len(updatedTables) == 0 && len(singleTables) == 1 { |
| 288 | for _, ref := range singleTables { |
| 289 | return []statementInfo{{ |
| 290 | statement: stmtText, |
| 291 | table: ref, |
| 292 | node: n, |
| 293 | fullSQL: fullSQL, |
| 294 | }}, nil |
no test coverage detected