github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/kvstore/query.go (about) 1 // Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . 2 3 package kvstore 4 5 import ( 6 "bytes" 7 "errors" 8 "fmt" 9 byteutils "github.com/TeaOSLab/EdgeNode/internal/utils/byte" 10 ) 11 12 type DataType = int 13 14 const ( 15 DataTypeKey DataType = 1 16 DataTypeField DataType = 2 17 ) 18 19 type QueryOperator int 20 21 const ( 22 QueryOperatorGt QueryOperator = 1 23 QueryOperatorGte QueryOperator = 2 24 QueryOperatorLt QueryOperator = 3 25 QueryOperatorLte QueryOperator = 4 26 ) 27 28 type QueryOperatorInfo struct { 29 Operator QueryOperator 30 Value any 31 } 32 33 type IteratorFunc[T any] func(tx *Tx[T], item Item[T]) (goNext bool, err error) 34 35 type Query[T any] struct { 36 table *Table[T] 37 tx *Tx[T] 38 39 dataType int 40 offsetKey string 41 limit int 42 prefix string 43 reverse bool 44 forUpdate bool 45 46 keysOnly bool 47 48 fieldName string 49 fieldReverse bool 50 fieldOperators []QueryOperatorInfo 51 fieldPrefix string 52 fieldOffsetKey []byte 53 } 54 55 func NewQuery[T any]() *Query[T] { 56 return &Query[T]{ 57 limit: -1, 58 dataType: DataTypeKey, 59 } 60 } 61 62 func (this *Query[T]) SetTable(table *Table[T]) *Query[T] { 63 this.table = table 64 return this 65 } 66 67 func (this *Query[T]) SetTx(tx *Tx[T]) *Query[T] { 68 this.tx = tx 69 return this 70 } 71 72 func (this *Query[T]) ForKey() *Query[T] { 73 this.dataType = DataTypeKey 74 return this 75 } 76 77 func (this *Query[T]) ForField() *Query[T] { 78 this.dataType = DataTypeField 79 return this 80 } 81 82 func (this *Query[T]) Limit(limit int) *Query[T] { 83 this.limit = limit 84 return this 85 } 86 87 func (this *Query[T]) Offset(offsetKey string) *Query[T] { 88 this.offsetKey = offsetKey 89 return this 90 } 91 92 func (this *Query[T]) Prefix(prefix string) *Query[T] { 93 this.prefix = prefix 94 return this 95 } 96 97 func (this *Query[T]) Desc() *Query[T] { 98 this.reverse = true 99 return this 100 } 101 102 func (this *Query[T]) ForUpdate() *Query[T] { 103 this.forUpdate = true 104 return this 105 } 106 107 func (this *Query[T]) KeysOnly() *Query[T] { 108 this.keysOnly = true 109 return this 110 } 111 112 func (this *Query[T]) FieldAsc(fieldName string) *Query[T] { 113 this.fieldName = fieldName 114 this.fieldReverse = false 115 return this 116 } 117 118 func (this *Query[T]) FieldDesc(fieldName string) *Query[T] { 119 this.fieldName = fieldName 120 this.fieldReverse = true 121 return this 122 } 123 124 func (this *Query[T]) FieldPrefix(fieldName string, fieldPrefix string) *Query[T] { 125 this.fieldName = fieldName 126 this.fieldPrefix = fieldPrefix 127 return this 128 } 129 130 func (this *Query[T]) FieldOffset(fieldOffset []byte) *Query[T] { 131 this.fieldOffsetKey = fieldOffset 132 return this 133 } 134 135 //func (this *Query[T]) FieldLt(value any) *Query[T] { 136 // this.fieldOperators = append(this.fieldOperators, QueryOperatorInfo{ 137 // Operator: QueryOperatorLt, 138 // Value: value, 139 // }) 140 // return this 141 //} 142 // 143 //func (this *Query[T]) FieldLte(value any) *Query[T] { 144 // this.fieldOperators = append(this.fieldOperators, QueryOperatorInfo{ 145 // Operator: QueryOperatorLte, 146 // Value: value, 147 // }) 148 // return this 149 //} 150 // 151 //func (this *Query[T]) FieldGt(value any) *Query[T] { 152 // this.fieldOperators = append(this.fieldOperators, QueryOperatorInfo{ 153 // Operator: QueryOperatorGt, 154 // Value: value, 155 // }) 156 // return this 157 //} 158 // 159 //func (this *Query[T]) FieldGte(value any) *Query[T] { 160 // this.fieldOperators = append(this.fieldOperators, QueryOperatorInfo{ 161 // Operator: QueryOperatorGte, 162 // Value: value, 163 // }) 164 // return this 165 //} 166 167 func (this *Query[T]) FindAll(fn IteratorFunc[T]) (err error) { 168 if this.table != nil && this.table.isClosed { 169 return NewTableClosedErr(this.table.name) 170 } 171 172 defer func() { 173 var panicErr = recover() 174 if panicErr != nil { 175 resultErr, ok := panicErr.(error) 176 if ok { 177 err = fmt.Errorf("execute query failed: %w", resultErr) 178 } 179 } 180 }() 181 182 if this.tx != nil { 183 defer func() { 184 _ = this.tx.Close() 185 }() 186 187 var itErr error 188 if len(this.fieldName) == 0 { 189 itErr = this.iterateKeys(fn) 190 } else { 191 itErr = this.iterateFields(fn) 192 } 193 if itErr != nil { 194 return itErr 195 } 196 return this.tx.Commit() 197 } 198 199 if this.table != nil { 200 var txFn func(fn func(tx *Tx[T]) error) error 201 if this.forUpdate { 202 txFn = this.table.WriteTx 203 } else { 204 txFn = this.table.ReadTx 205 } 206 207 return txFn(func(tx *Tx[T]) error { 208 this.tx = tx 209 210 if len(this.fieldName) == 0 { 211 return this.iterateKeys(fn) 212 } 213 return this.iterateFields(fn) 214 }) 215 } 216 217 return errors.New("current query require 'table' or 'tx'") 218 } 219 220 func (this *Query[T]) iterateKeys(fn IteratorFunc[T]) error { 221 if this.limit == 0 { 222 return nil 223 } 224 225 var opt = &IteratorOptions{} 226 227 var prefix []byte 228 switch this.dataType { 229 case DataTypeKey: 230 prefix = byteutils.Append(this.table.Namespace(), []byte(KeyPrefix)...) 231 case DataTypeField: 232 prefix = byteutils.Append(this.table.Namespace(), []byte(FieldPrefix)...) 233 default: 234 prefix = byteutils.Append(this.table.Namespace(), []byte(KeyPrefix)...) 235 } 236 237 var prefixLen = len(prefix) 238 239 if len(this.prefix) > 0 { 240 prefix = append(prefix, this.prefix...) 241 } 242 243 var offsetKey []byte 244 if this.reverse { 245 if len(this.offsetKey) > 0 { 246 offsetKey = byteutils.Append(prefix, []byte(this.offsetKey)...) 247 } else { 248 offsetKey = byteutils.Append(prefix, 0xFF) 249 } 250 251 opt.LowerBound = prefix 252 opt.UpperBound = offsetKey 253 } else { 254 if len(this.offsetKey) > 0 { 255 offsetKey = byteutils.Append(prefix, []byte(this.offsetKey)...) 256 } else { 257 offsetKey = prefix 258 } 259 opt.LowerBound = offsetKey 260 opt.UpperBound = byteutils.Append(prefix, 0xFF) 261 } 262 263 var hasOffsetKey = len(this.offsetKey) > 0 264 265 it, itErr := this.tx.NewIterator(opt) 266 if itErr != nil { 267 return itErr 268 } 269 defer func() { 270 _ = it.Close() 271 }() 272 273 var count int 274 275 var itemFn = func() (goNextItem bool, err error) { 276 var keyBytes = it.Key() 277 278 // skip first offset key 279 if hasOffsetKey { 280 hasOffsetKey = false 281 282 if bytes.Equal(keyBytes, offsetKey) { 283 return true, nil 284 } 285 } 286 287 // call fn 288 var value T 289 if !this.keysOnly { 290 valueBytes, valueErr := it.ValueAndErr() 291 if valueErr != nil { 292 return false, valueErr 293 } 294 value, err = this.table.encoder.Decode(valueBytes) 295 if err != nil { 296 return false, err 297 } 298 } 299 300 goNext, callbackErr := fn(this.tx, Item[T]{ 301 Key: string(keyBytes[prefixLen:]), 302 Value: value, 303 }) 304 if callbackErr != nil { 305 if IsSkipError(callbackErr) { 306 return true, nil 307 } else { 308 return false, callbackErr 309 } 310 } 311 if !goNext { 312 return false, nil 313 } 314 315 // limit 316 if this.limit > 0 { 317 count++ 318 319 if count >= this.limit { 320 return false, nil 321 } 322 } 323 324 return true, nil 325 } 326 327 if this.reverse { 328 for it.Last(); it.Valid(); it.Prev() { 329 goNext, itemErr := itemFn() 330 if itemErr != nil { 331 return itemErr 332 } 333 if !goNext { 334 break 335 } 336 } 337 } else { 338 for it.First(); it.Valid(); it.Next() { 339 goNext, itemErr := itemFn() 340 if itemErr != nil { 341 return itemErr 342 } 343 if !goNext { 344 break 345 } 346 } 347 } 348 349 return nil 350 } 351 352 func (this *Query[T]) iterateFields(fn IteratorFunc[T]) error { 353 if this.limit == 0 { 354 return nil 355 } 356 357 var hasOffsetKey = len(this.offsetKey) > 0 || len(this.fieldOffsetKey) > 0 358 359 var opt = &IteratorOptions{} 360 361 var prefix = this.table.FieldKey(this.fieldName) 362 prefix = append(prefix, '$') 363 364 if len(this.fieldPrefix) > 0 { 365 prefix = append(prefix, this.fieldPrefix...) 366 } 367 368 var offsetKey []byte 369 if this.fieldReverse { 370 if len(this.fieldOffsetKey) > 0 { 371 offsetKey = this.fieldOffsetKey 372 } else if len(this.offsetKey) > 0 { 373 offsetKey = byteutils.Append(prefix, []byte(this.offsetKey)...) 374 } else { 375 offsetKey = byteutils.Append(prefix, 0xFF) 376 } 377 opt.LowerBound = prefix 378 opt.UpperBound = offsetKey 379 } else { 380 if len(this.fieldOffsetKey) > 0 { 381 offsetKey = this.fieldOffsetKey 382 } else if len(this.offsetKey) > 0 { 383 offsetKey = byteutils.Append(prefix, []byte(this.offsetKey)...) 384 offsetKey = append(offsetKey, 0) 385 } else { 386 offsetKey = prefix 387 } 388 389 opt.LowerBound = offsetKey 390 opt.UpperBound = byteutils.Append(prefix, 0xFF) 391 } 392 393 it, itErr := this.tx.NewIterator(opt) 394 if itErr != nil { 395 return itErr 396 } 397 defer func() { 398 _ = it.Close() 399 }() 400 401 var count int 402 403 var itemFn = func() (goNextItem bool, err error) { 404 var fieldKeyBytes = it.Key() 405 406 fieldValueBytes, keyBytes, decodeKeyErr := this.table.DecodeFieldKey(this.fieldName, fieldKeyBytes) 407 if decodeKeyErr != nil { 408 return false, decodeKeyErr 409 } 410 411 // skip first offset key 412 if hasOffsetKey { 413 hasOffsetKey = false 414 415 if (len(this.fieldOffsetKey) > 0 && bytes.Equal(fieldKeyBytes, this.fieldOffsetKey)) || 416 bytes.Equal(fieldValueBytes, []byte(this.offsetKey)) { 417 return true, nil 418 } 419 } 420 421 // 执行operators 422 if len(this.fieldOperators) > 0 { 423 if !this.matchOperators(fieldValueBytes) { 424 return true, nil 425 } 426 } 427 428 var resultItem = Item[T]{ 429 Key: string(keyBytes), 430 FieldKey: fieldKeyBytes, 431 } 432 if !this.keysOnly { 433 value, getErr := this.table.getWithKeyBytes(this.tx, this.table.FullKeyBytes(keyBytes)) 434 if getErr != nil { 435 if IsNotFound(getErr) { 436 return true, nil 437 } 438 return false, getErr 439 } 440 441 resultItem.Value = value 442 } 443 444 goNextItem, err = fn(this.tx, resultItem) 445 if err != nil { 446 if IsSkipError(err) { 447 return true, nil 448 } else { 449 return false, err 450 } 451 } 452 if !goNextItem { 453 return false, nil 454 } 455 456 // limit 457 if this.limit > 0 { 458 count++ 459 460 if count >= this.limit { 461 return false, nil 462 } 463 } 464 465 return true, nil 466 } 467 468 if this.reverse { 469 for it.Last(); it.Valid(); it.Prev() { 470 goNext, itemErr := itemFn() 471 if itemErr != nil { 472 return itemErr 473 } 474 if !goNext { 475 break 476 } 477 } 478 } else { 479 for it.First(); it.Valid(); it.Next() { 480 goNext, itemErr := itemFn() 481 if itemErr != nil { 482 return itemErr 483 } 484 if !goNext { 485 break 486 } 487 } 488 } 489 490 return nil 491 } 492 493 func (this *Query[T]) matchOperators(fieldValueBytes []byte) bool { 494 // TODO 495 return true 496 }