github.com/vedadiyan/sqlparser@v1.0.0/pkg/sqlparser/utils.go (about) 1 /* 2 Copyright 2020 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sqlparser 18 19 import ( 20 "fmt" 21 "sort" 22 23 querypb "github.com/vedadiyan/sqlparser/pkg/query" 24 ) 25 26 // QueryMatchesTemplates sees if the given query has the same fingerprint as one of the given templates 27 // (one is enough) 28 func QueryMatchesTemplates(query string, queryTemplates []string) (match bool, err error) { 29 if len(queryTemplates) == 0 { 30 return false, fmt.Errorf("No templates found") 31 } 32 bv := make(map[string]*querypb.BindVariable) 33 34 normalize := func(q string) (string, error) { 35 q, err := NormalizeAlphabetically(q) 36 if err != nil { 37 return "", err 38 } 39 stmt, reservedVars, err := Parse2(q) 40 if err != nil { 41 return "", err 42 } 43 err = Normalize(stmt, NewReservedVars("", reservedVars), bv) 44 if err != nil { 45 return "", err 46 } 47 normalized := CanonicalString(stmt) 48 return normalized, nil 49 } 50 51 normalizedQuery, err := normalize(query) 52 if err != nil { 53 return false, err 54 } 55 56 for _, template := range queryTemplates { 57 normalizedTemplate, err := normalize(template) 58 if err != nil { 59 return false, err 60 } 61 62 // compare! 63 if normalizedTemplate == normalizedQuery { 64 return true, nil 65 } 66 } 67 return false, nil 68 } 69 70 // NormalizeAlphabetically rewrites given query such that: 71 // - WHERE 'AND' expressions are reordered alphabetically 72 func NormalizeAlphabetically(query string) (normalized string, err error) { 73 stmt, err := Parse(query) 74 if err != nil { 75 return normalized, err 76 } 77 var where *Where 78 switch stmt := stmt.(type) { 79 case *Update: 80 where = stmt.Where 81 case *Delete: 82 where = stmt.Where 83 case *Select: 84 where = stmt.Where 85 } 86 if where != nil { 87 andExprs := SplitAndExpression(nil, where.Expr) 88 sort.SliceStable(andExprs, func(i, j int) bool { 89 return String(andExprs[i]) < String(andExprs[j]) 90 }) 91 var newWhere *Where 92 for _, expr := range andExprs { 93 if newWhere == nil { 94 newWhere = &Where{ 95 Type: WhereClause, 96 Expr: expr, 97 } 98 } else { 99 newWhere.Expr = &AndExpr{ 100 Left: newWhere.Expr, 101 Right: expr, 102 } 103 } 104 } 105 switch stmt := stmt.(type) { 106 case *Update: 107 stmt.Where = newWhere 108 case *Delete: 109 stmt.Where = newWhere 110 case *Select: 111 stmt.Where = newWhere 112 } 113 } 114 return String(stmt), nil 115 }