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)) } sand := newSubsetAnd(and.(*expression.And)) rv := &subsetLike{} rv.test = func(expr2 expression.Expression) (bool, error) { if expr.EquivalentTo(expr2) { return true, nil } return sand.test(expr2) } return rv }
func newSargLike(pred expression.BinaryFunction, re *regexp.Regexp) expression.Visitor { prefix := "" if re != nil { var complete bool prefix, complete = re.LiteralPrefix() if complete { eq := expression.NewEq(pred.First(), expression.NewConstant(prefix)) return newSargEq(eq.(*expression.Eq)) } } rv := &sargLike{} rv.sarger = func(expr2 expression.Expression) (plan.Spans, error) { if SubsetOf(pred, expr2) { return _SELF_SPANS, nil } if !pred.First().EquivalentTo(expr2) { return nil, nil } span := &plan.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 plan.Spans{span}, nil } return rv }
func (this *builder) buildScan(keyspace datastore.Keyspace, node *algebra.KeyspaceTerm, limit expression.Expression) ( secondary plan.Operator, primary *plan.PrimaryScan, err error) { var indexes, hintIndexes, otherIndexes []datastore.Index hints := node.Indexes() if hints != nil { indexes, err = allHints(keyspace, hints) hintIndexes = indexes } else { indexes, err = allIndexes(keyspace) otherIndexes = indexes } if err != nil { return } pred := this.where if pred != nil { dnf := NewDNF() pred = pred.Copy() pred, err = dnf.Map(pred) if err != nil { return } formalizer := expression.NewFormalizer() formalizer.Keyspace = node.Alias() primaryKey := expression.Expressions{ expression.NewField( expression.NewMeta(expression.NewConstant(node.Alias())), expression.NewFieldName("id", false)), } sargables, er := sargableIndexes(indexes, pred, primaryKey, dnf, formalizer) if er != nil { return nil, nil, er } minimals, er := minimalIndexes(sargables, pred) if er != nil { return nil, nil, er } if len(minimals) > 0 { secondary, err = this.buildSecondaryScan(minimals, node, limit) return secondary, nil, err } } primary, err = this.buildPrimaryScan(keyspace, node, limit, hintIndexes, otherIndexes) return nil, primary, err }
func (this *DNF) VisitLike(expr *expression.Like) (interface{}, error) { err := expr.MapChildren(this) if err != nil { return nil, err } re := expr.Regexp() if re == nil { return expr, nil } prefix, complete := re.LiteralPrefix() if complete { eq := expression.NewEq(expr.First(), expression.NewConstant(prefix)) return eq, nil } if prefix == "" { return expr, nil } 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 and, nil }
func (this *builder) buildJoinScan(keyspace datastore.Keyspace, node *algebra.KeyspaceTerm, op string) ( datastore.Index, expression.Covers, error) { indexes, err := allIndexes(keyspace) if err != nil { return nil, nil, err } var pred expression.Expression pred = expression.NewIsNotNull(node.Keys().Copy()) dnf := NewDNF() pred, err = dnf.Map(pred) if err != nil { return nil, nil, err } subset := pred if this.where != nil { subset = expression.NewAnd(subset, this.where.Copy()) subset, err = dnf.Map(subset) if err != nil { return nil, nil, err } } formalizer := expression.NewFormalizer() formalizer.Keyspace = node.Alias() primaryKey := expression.Expressions{ expression.NewField( expression.NewMeta(expression.NewConstant(node.Alias())), expression.NewFieldName("id", false)), } sargables, err := sargableIndexes(indexes, pred, subset, primaryKey, dnf, formalizer) if err != nil { return nil, nil, err } minimals, err := minimalIndexes(sargables, pred) if err != nil { return nil, nil, err } if len(minimals) == 0 { return nil, nil, errors.NewNoIndexJoinError(node.Alias(), op) } return this.buildCoveringJoinScan(minimals, node, op) }
return this.VisitAnd(and) 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()) default: return expr, nil } return exp, exp.MapChildren(this) } var _EMPTY_OBJECT_EXPR = expression.NewConstant(map[string]interface{}{}) var _MIN_BINARY_EXPR = expression.NewConstant([]byte{}) func (this *DNF) 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 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)) }