MCPcopy Create free account
hub / github.com/bytebase/bytebase / updateMutatesTable

Function updateMutatesTable

backend/plugin/parser/tidb/restore.go:573–628  ·  view source on GitHub ↗

updateMutatesTable reports whether the UPDATE's SET clauses actually mutate (a column of) the specified table. JOIN-only references that do not appear as a SET-clause qualifier do NOT count as mutation. Resolution strategy mirrors extractUpdateColumns: build the alias map (lowercased per Bug 5), th

(stmt *ast.UpdateStmt, database, table string, targetCols map[string]bool)

Source from the content-addressed store, hash-verified

571// UPDATE with unqualified col is ambiguous; safer to over-include than
572// miss).
573func updateMutatesTable(stmt *ast.UpdateStmt, database, table string, targetCols map[string]bool) bool {
574 // Precondition: target must be in stmt.Tables at all (else there's
575 // nothing to discuss).
576 targetInScope := false
577 for _, expr := range stmt.Tables {
578 if tableExprReferences(expr, database, table) {
579 targetInScope = true
580 break
581 }
582 }
583 if !targetInScope {
584 return false
585 }
586
587 singleTables := extractSingleTablesFromTableExprs(database, stmt.Tables)
588 for _, assignment := range stmt.SetList {
589 col := assignment.Column
590 if col == nil {
591 continue
592 }
593 if col.Schema != "" && !strings.EqualFold(col.Schema, database) {
594 continue
595 }
596 if col.Table == "" {
597 // Unqualified column. Resolve against the target table's
598 // actual columns — only count as mutation if the column
599 // exists on the target. Pre-fix this branch returned true
600 // unconditionally (over-counted); for `UPDATE test JOIN t1
601 // ON ... SET name = 1` where `name` is on t1 but not test,
602 // the over-count produced empty `... ON DUPLICATE KEY
603 // UPDATE ;`. Per Codex P1 catch on PR #20345.
604 if targetCols[strings.ToLower(col.Column)] {
605 return true
606 }
607 continue
608 }
609 // Qualified — resolve qualifier through the alias map. Both
610 // Database AND Table must match: for cross-database joins with
611 // homonymous tables (e.g. `UPDATE db1.test t1 JOIN db2.test t2
612 // SET t2.a = ...`), the alias t2 resolves to db2.test; without
613 // the Database check, a backup item targeting db1.test would
614 // incorrectly match db2.test's SET assignments. Per Codex P1
615 // catch on PR #20345.
616 if entry, ok := singleTables[strings.ToLower(col.Table)]; ok && strings.EqualFold(entry.Database, database) && strings.EqualFold(entry.Table, table) {
617 return true
618 }
619 // Fallback: qualifier IS the bare table name (no alias used).
620 // The col.Schema check at the top of the loop already filtered
621 // out assignments whose explicit schema doesn't match `database`,
622 // so reaching here implies col.Schema is empty or matches.
623 if strings.EqualFold(col.Table, table) {
624 return true
625 }
626 }
627 return false
628}
629
630func tableExprReferences(expr ast.TableExpr, database, table string) bool {

Callers 1

containsTableFunction · 0.85

Calls 2

tableExprReferencesFunction · 0.70

Tested by

no test coverage detected