github.com/polarismesh/polaris@v1.17.8/store/mysql/sql.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package sqldb 19 20 import ( 21 "fmt" 22 "strconv" 23 "strings" 24 25 "github.com/polarismesh/polaris/common/utils" 26 ) 27 28 const ( 29 30 // OwnerAttribute 31 OwnerAttribute string = "owner" 32 33 // And 34 And string = " and" 35 ) 36 37 // Order 排序结构体 38 type Order struct { 39 Filed string 40 Sequence string 41 } 42 43 // Page 分页结构体 44 type Page struct { 45 Offset uint32 46 Limit uint32 47 } 48 49 func boolToInt(v bool) int { 50 if v { 51 return 1 52 } 53 return 0 54 } 55 56 // genFilterSQL 根据filter生成where相关的语句 57 func genFilterSQL(filter map[string]string) (string, []interface{}) { 58 if len(filter) == 0 { 59 return "", nil 60 } 61 62 args := make([]interface{}, 0, len(filter)) 63 var str string 64 firstIndex := true 65 for key, value := range filter { 66 if !firstIndex { 67 str += And 68 } 69 firstIndex = false 70 // 这个查询组装,先这样完成,后续优化filter TODO 71 if key == OwnerAttribute || key == "alias."+OwnerAttribute || key == "business" { 72 str += fmt.Sprintf(" %s like ?", key) 73 value = "%" + value + "%" 74 } else if key == "name" && utils.IsWildName(value) { 75 str += " name like ?" 76 value = utils.ParseWildNameForSql(value) 77 } else if key == "id" { 78 if utils.IsWildName(value) { 79 str += " instance.id like ?" 80 value = utils.ParseWildNameForSql(value) 81 } else { 82 str += " instance.id = ?" 83 } 84 } else if key == "host" { 85 hosts := strings.Split(value, ",") 86 str += " host in (" + PlaceholdersN(len(hosts)) + ")" 87 for _, host := range hosts { 88 args = append(args, host) 89 } 90 } else if key == "managed" { 91 str += " managed = ?" 92 managed, _ := strconv.ParseBool(value) 93 args = append(args, boolToInt(managed)) 94 continue 95 } else if key == "namespace" && utils.IsWildName(value) { 96 str += " namespace like ?" 97 value = utils.ParseWildNameForSql(value) 98 } else { 99 str += " " + key + "=?" 100 } 101 if key != "host" { 102 args = append(args, value) 103 } 104 } 105 106 return str, args 107 } 108 109 // genServiceFilterSQL 根据service filter生成where相关的语句 110 func genServiceFilterSQL(filter map[string]string) (string, []interface{}) { 111 if len(filter) == 0 { 112 return "", nil 113 } 114 115 args := make([]interface{}, 0, len(filter)) 116 var str string 117 firstIndex := true 118 for key, value := range filter { 119 if !firstIndex { 120 str += And 121 } 122 firstIndex = false 123 124 if key == OwnerAttribute { 125 str += " (service.name, service.namespace) in (select service,namespace from owner_service_map where owner=?)" 126 } else if key == "alias."+OwnerAttribute { 127 str += " (alias.name, alias.namespace) in (select service,namespace from owner_service_map where owner=?)" 128 } else if key == "business" { 129 str += fmt.Sprintf(" %s like ?", key) 130 value = "%" + value + "%" 131 } else if key == "name" && utils.IsPrefixWildName(value) { 132 str += " name like ?" 133 value = "%" + value[0:len(value)-1] + "%" 134 } else { 135 str += " " + key + "=?" 136 } 137 138 args = append(args, value) 139 } 140 141 return str, args 142 } 143 144 // genRuleFilterSQL 根据规则的filter生成where相关的语句 145 func genRuleFilterSQL(tableName string, filter map[string]string) (string, []interface{}) { 146 if len(filter) == 0 { 147 return "", nil 148 } 149 150 args := make([]interface{}, 0, len(filter)) 151 var str string 152 firstIndex := true 153 for key, value := range filter { 154 if tableName != "" { 155 key = tableName + "." + key 156 } 157 if !firstIndex { 158 str += And 159 } 160 if key == OwnerAttribute || key == (tableName+"."+OwnerAttribute) { 161 str += fmt.Sprintf(" %s like ? ", key) 162 value = "%" + value + "%" 163 } else { 164 str += " " + key + " = ? " 165 } 166 args = append(args, value) 167 firstIndex = false 168 } 169 return str, args 170 } 171 172 // genOrderAndPage 生成order和page相关语句 173 func genOrderAndPage(order *Order, page *Page) (string, []interface{}) { 174 var str string 175 var args []interface{} 176 if order != nil { 177 str += " order by " + order.Filed + " " + order.Sequence 178 } 179 if page != nil { 180 str += " limit ?, ?" 181 args = append(args, page.Offset, page.Limit) 182 } 183 184 return str, args 185 } 186 187 // genWhereSQLAndArgs 生成service和instance查询数据的where语句和对应参数 188 func genWhereSQLAndArgs(str string, filter, metaFilter map[string]string, order *Order, offset uint32, limit uint32) ( 189 string, []interface{}) { 190 baseStr := str 191 var args []interface{} 192 filterStr, filterArgs := genFilterSQL(filter) 193 var conjunction string = " where " 194 if filterStr != "" { 195 baseStr += " where " + filterStr 196 conjunction = " and " 197 } 198 args = append(args, filterArgs...) 199 var metaStr string 200 var metaArgs []interface{} 201 if len(metaFilter) > 0 { 202 metaStr, metaArgs = genInstanceMetadataArgs(metaFilter) 203 args = append(args, metaArgs...) 204 baseStr += conjunction + metaStr 205 } 206 page := &Page{offset, limit} 207 opStr, opArgs := genOrderAndPage(order, page) 208 209 return baseStr + opStr, append(args, opArgs...) 210 } 211 212 func genInstanceMetadataArgs(metaFilter map[string]string) (string, []interface{}) { 213 str := `instance.id in (select id from instance_metadata where mkey = ? and mvalue = ?)` 214 args := make([]interface{}, 0, 2) 215 for k, v := range metaFilter { 216 args = append(args, k) 217 args = append(args, v) 218 } 219 return str, args 220 } 221 222 // genServiceAliasWhereSQLAndArgs 生成service alias查询数据的where语句和对应参数 223 func genServiceAliasWhereSQLAndArgs(str string, filter map[string]string, order *Order, offset uint32, limit uint32) ( 224 string, []interface{}) { 225 baseStr := str 226 filterStr, filterArgs := genServiceFilterSQL(filter) 227 if filterStr != "" { 228 baseStr += " where " 229 } 230 page := &Page{offset, limit} 231 opStr, opArgs := genOrderAndPage(order, page) 232 233 return baseStr + filterStr + opStr, append(filterArgs, opArgs...) 234 } 235 236 // genNamespaceWhereSQLAndArgs 生成namespace查询数据的where语句和对应参数 237 func genNamespaceWhereSQLAndArgs(str string, filter map[string][]string, order *Order, offset, limit int) ( 238 string, []interface{}) { 239 num := 0 240 for _, value := range filter { 241 num += len(value) 242 } 243 args := make([]interface{}, 0, num+2) 244 245 if num > 0 { 246 str += "where" 247 firstIndex := true 248 249 for index, value := range filter { 250 if !firstIndex { 251 str += And 252 } 253 str += " (" 254 255 firstItem := true 256 for _, item := range value { 257 if !firstItem { 258 str += " or " 259 } 260 if index == OwnerAttribute { 261 str += "owner like ?" 262 item = "%" + item + "%" 263 } else { 264 if index == NameAttribute && utils.IsWildName(item) { 265 str += "name like ?" 266 item = utils.ParseWildNameForSql(item) 267 } else { 268 str += index + "=?" 269 } 270 } 271 args = append(args, item) 272 firstItem = false 273 } 274 firstIndex = false 275 str += ")" 276 } 277 } 278 279 if order != nil { 280 str += " order by " + order.Filed + " " + order.Sequence 281 } 282 283 str += " limit ?, ?" 284 args = append(args, offset, limit) 285 286 return str, args 287 } 288 289 // filterMetadataWithTable 根据metadata属性过滤 290 // 生成子查询语句 291 // 多个metadata,取交集(and) 292 func filterMetadataWithTable(table string, metas map[string]string) (string, []interface{}) { 293 str := "(select id from " + table + " where mkey = ? and mvalue = ?)" 294 args := make([]interface{}, 0, 2) 295 for key, value := range metas { 296 args = append(args, key) 297 args = append(args, value) 298 } 299 300 return str, args 301 } 302 303 // PlaceholdersN 构造多个占位符 304 func PlaceholdersN(size int) string { 305 if size <= 0 { 306 return "" 307 } 308 str := strings.Repeat("?,", size) 309 return str[0 : len(str)-1] 310 }