SQLReviewCheck checks the statements with sql review rules.
( ctx context.Context, sm *sheet.Manager, statements string, ruleList []*storepb.SQLReviewRule, checkContext Context, )
| 91 | |
| 92 | // SQLReviewCheck checks the statements with sql review rules. |
| 93 | func SQLReviewCheck( |
| 94 | ctx context.Context, |
| 95 | sm *sheet.Manager, |
| 96 | statements string, |
| 97 | ruleList []*storepb.SQLReviewRule, |
| 98 | checkContext Context, |
| 99 | ) ([]*storepb.Advice, error) { |
| 100 | stmts, parseResult := sm.GetStatementsForChecks(checkContext.DBType, statements) |
| 101 | asts := base.ExtractASTs(stmts) |
| 102 | |
| 103 | if !checkContext.NoAppendBuiltin { |
| 104 | // Append builtin rules only if the user hasn't overridden them in their config. |
| 105 | userRuleTypes := make(map[storepb.SQLReviewRule_Type]bool, len(ruleList)) |
| 106 | for _, r := range ruleList { |
| 107 | userRuleTypes[r.Type] = true |
| 108 | } |
| 109 | for _, r := range GetBuiltinRules(checkContext.DBType) { |
| 110 | if !userRuleTypes[r.Type] { |
| 111 | ruleList = append(ruleList, r) |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | if asts == nil || len(ruleList) == 0 { |
| 117 | return parseResult, nil |
| 118 | } |
| 119 | |
| 120 | if checkContext.FinalMetadata != nil { |
| 121 | walkThroughContext := schema.WalkThroughContext{ |
| 122 | SessionUser: checkContext.SessionUser, |
| 123 | RawSQL: statements, |
| 124 | } |
| 125 | if advice := schema.WalkThroughWithContext(checkContext.DBType, walkThroughContext, checkContext.FinalMetadata, asts); advice != nil { |
| 126 | for _, rule := range ruleList { |
| 127 | if rule.Type == storepb.SQLReviewRule_BUILTIN_WALK_THROUGH_CHECK { |
| 128 | if status, err := NewStatusBySQLReviewRuleLevel(rule.Level); err == nil { |
| 129 | advice.Status = status |
| 130 | } |
| 131 | return []*storepb.Advice{advice}, nil |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | // Initialize the per-review memo so engine-specific helpers can amortize |
| 138 | // work across rules (e.g. omni re-parsing in advisor/tidb). The map header |
| 139 | // propagates by value across rules; the underlying map is shared. |
| 140 | checkContext.memo = make(map[string]any) |
| 141 | |
| 142 | var errorAdvices, warningAdvices []*storepb.Advice |
| 143 | for _, rule := range ruleList { |
| 144 | if rule.Engine != storepb.Engine_ENGINE_UNSPECIFIED && rule.Engine != checkContext.DBType { |
| 145 | continue |
| 146 | } |
| 147 | |
| 148 | ruleType := rule.Type |
| 149 | |
| 150 | // Set per-rule fields |