func newSubsetLike(expr expression.BinaryFunction, re *regexp.Regexp) expression.Visitor { if re == nil { // Pattern is not a constant return newSubsetDefault(expr) } prefix, complete := re.LiteralPrefix() if complete { eq := expression.NewEq(expr.First(), expression.NewConstant(prefix)) return newSubsetEq(eq.(*expression.Eq)) } if prefix == "" { return newSubsetDefault(expr) } var and expression.Expression le := expression.NewLE(expression.NewConstant(prefix), expr.First()) last := len(prefix) - 1 if prefix[last] < math.MaxUint8 { bytes := []byte(prefix) bytes[last]++ and = expression.NewAnd(le, expression.NewLT( expr.First(), expression.NewConstant(string(bytes)))) } else { and = expression.NewAnd(le, expression.NewLT( expr.First(), expression.EMPTY_ARRAY_EXPR)) } return newSubsetAnd(and.(*expression.And)) }
func newSargLike(expr expression.BinaryFunction, re *regexp.Regexp) expression.Visitor { prefix := "" if re != nil { prefix, complete := re.LiteralPrefix() if complete { eq := expression.NewEq(expr.First(), expression.NewConstant(prefix)) return newSargEq(eq.(*expression.Eq)) } } rv := &sargLike{} rv.sarg = func(expr2 expression.Expression) (Spans, error) { if expr.EquivalentTo(expr2) { return _SELF_SPANS, nil } if !expr.First().EquivalentTo(expr2) { return nil, nil } span := &Span{} span.Range.Low = expression.Expressions{expression.NewConstant(prefix)} last := len(prefix) - 1 if last >= 0 && prefix[last] < math.MaxUint8 { bytes := []byte(prefix) bytes[last]++ span.Range.High = expression.Expressions{expression.NewConstant(string(bytes))} } else { span.Range.High = _EMPTY_ARRAY } span.Range.Inclusion = datastore.LOW return Spans{span}, nil } return rv }
func constantArray(constant []interface{}) expression.Expression { return expression.NewArrayConstruct(expression.NewConstant(value.NewValue(constant))) }
func constant(constant interface{}) expression.Expression { return expression.NewConstant(value.NewValue(constant)) }
} exp = expression.NewAnd(operands...) case *expression.Eq: exp = expression.NewOr(expression.NewLT(operand.First(), operand.Second()), expression.NewLT(operand.Second(), operand.First())) case *expression.LT: exp = expression.NewLE(operand.Second(), operand.First()) case *expression.LE: exp = expression.NewLT(operand.Second(), operand.First()) } return exp, exp.MapChildren(this) } var _EMPTY_OBJECT_EXPR = expression.NewConstant(map[string]interface{}{}) var _MIN_BINARY_EXPR = expression.NewConstant([]byte{}) func (this *NNF) VisitFunction(expr expression.Function) (interface{}, error) { var exp expression.Expression = expr switch expr := expr.(type) { case *expression.IsBoolean: exp = expression.NewLE(expr.Operand(), expression.TRUE_EXPR) case *expression.IsNumber: exp = expression.NewAnd( expression.NewGT(expr.Operand(), expression.TRUE_EXPR), expression.NewLT(expr.Operand(), expression.EMPTY_STRING_EXPR)) case *expression.IsString: exp = expression.NewAnd( expression.NewGE(expr.Operand(), expression.EMPTY_STRING_EXPR),
func (this *builder) selectScan(keyspace datastore.Keyspace, node *algebra.KeyspaceTerm) (Operator, error) { if this.where == nil { return this.selectPrimaryScan(keyspace, node) } nnf := planner.NewNNF() where := this.where.Copy() where, err := nnf.Map(where) if err != nil { return nil, err } formalizer := expression.NewFormalizer() formalizer.Keyspace = node.Alias() primaryKey := expression.NewField( expression.NewMeta(expression.NewConstant(node.Alias())), expression.NewFieldName("id")) indexers, err := keyspace.Indexers() if err != nil { return nil, err } indexes := make([]datastore.Index, 0, len(indexers)*16) primaryIndexes := make(map[datastore.Index]bool, len(indexers)*2) for _, indexer := range indexers { idxs, err := indexer.Indexes() if err != nil { return nil, err } indexes = append(indexes, idxs...) primaryIdxs, err := indexer.PrimaryIndexes() if err != nil { return nil, err } for _, p := range primaryIdxs { primaryIndexes[p] = true } } unfiltered := make(map[datastore.Index]expression.Expression, len(indexes)) filtered := make(map[datastore.Index]expression.Expression, len(indexes)) for _, index := range indexes { state, _, er := index.State() if er != nil { return nil, er } if state != datastore.ONLINE { continue } var key expression.Expression if primaryIndexes[index] { key = primaryKey } else { rangeKey := index.RangeKey() if len(rangeKey) == 0 || rangeKey[0] == nil { // Index not rangeable continue } key := rangeKey[0].Copy() key, err = formalizer.Map(key) if err != nil { return nil, err } key, err = nnf.Map(key) if err != nil { return nil, err } } if !planner.SargableFor(where, key) { // Index not applicable continue } indexCond := index.Condition() if indexCond == nil { unfiltered[index] = key continue } indexCond = indexCond.Copy() indexCond, err = formalizer.Map(indexCond) if err != nil { return nil, err } indexCond, err = nnf.Map(indexCond) if err != nil { return nil, err } if planner.SubsetOf(where, indexCond) { // Index condition satisfies query condition filtered[index] = key break } } var indexMap map[datastore.Index]expression.Expression if len(filtered) > 0 { indexMap = filtered } else if len(unfiltered) > 0 { indexMap = unfiltered } for index, key := range indexMap { spans := planner.SargFor(where, key) var scan Operator scan = NewIndexScan(index, node, spans, false, math.MaxInt64) if len(spans) > 1 { // Use UnionScan to de-dup multiple spans scan = NewUnionScan(scan) } return scan, err } return this.selectPrimaryScan(keyspace, node) }