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  }