Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
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
}
Ejemplo n.º 4
0
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
}
Ejemplo n.º 5
0
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)
}
Ejemplo n.º 6
0
		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),
Ejemplo n.º 7
0
func constantArray(constant []interface{}) expression.Expression {
	return expression.NewArrayConstruct(expression.NewConstant(value.NewValue(constant)))
}
Ejemplo n.º 8
0
func constant(constant interface{}) expression.Expression {
	return expression.NewConstant(value.NewValue(constant))
}