blob: 0f90ddbc0544a61429530e6f764d2262d58fb390 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
import java.util.Set;
import org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.jetbrains.annotations.NotNull;
/**
* The base class for constraints.
*/
public abstract class ConstraintImpl extends AstElement {
/**
* Simplify the expression if possible, for example by removing duplicate expressions.
* For example, "x=1 or x=1" should be simplified to "x=1".
*
* @return the simplified constraint, or "this" if it is not possible to simplify
*/
public ConstraintImpl simplify() {
return this;
}
/**
* Get the negative constraint, if it is simpler, or null. For example,
* "not x = 1" returns "x = 1", but "x = 1" returns null.
*
* @return the negative constraint, or null
*/
ConstraintImpl not() {
return null;
}
/**
* Evaluate the result using the currently set values.
*
* @return true if the constraint matches
*/
public abstract boolean evaluate();
/**
* Whether this condition will, from now on, always evaluate to false. This
* is the case for example for full-text constraints if there is no
* full-text index (unless FullTextComparisonWithoutIndex is enabled). This
* will also allow is to add conditions that stop further processing for
* other reasons, similar to {@code "WHERE ROWNUM < 10"} in Oracle.
*
* @return true if further processing should be stopped
*/
public boolean evaluateStop() {
return false;
}
/**
* Get the set of property existence conditions that can be derived for this
* condition. For example, for the condition "x=1 or x=2", the property
* existence condition is "x is not null". For the condition "x=1 or y=2",
* there is no such condition. For the condition "x=1 and y=1", there are
* two (x is not null, and y is not null).
*
* @return the common property existence condition (possibly empty)
*/
public abstract Set<PropertyExistenceImpl> getPropertyExistenceConditions();
/**
* Get the (combined) full-text constraint. For constraints of the form
* "contains(*, 'x') or contains(*, 'y')", the combined expression is
* returned. If there is none, null is returned. For constraints of the form
* "contains(*, 'x') or z=1", null is returned as the full-text index cannot
* be used in this case for filtering (as it might filter out the z=1
* nodes).
*
* @param s the selector
* @return the full-text constraint, if there is any, or null if not
*/
public FullTextExpression getFullTextConstraint(SelectorImpl s) {
return null;
}
/**
* Get the set of selectors for the given condition.
*
* @return the set of selectors (possibly empty)
*/
public abstract Set<SelectorImpl> getSelectors();
/**
* Apply the condition to the filter, further restricting the filter if
* possible. This may also verify the data types are compatible, and that
* paths are valid.
*
* @param f the filter
*/
public abstract void restrict(FilterImpl f);
/**
* Push as much of the condition down to this selector, further restricting
* the selector condition if possible. This is important for a join: for
* example, the query
* "select * from a inner join b on a.x=b.x where a.y=1 and b.y=1", the
* condition "a.y=1" can be pushed down to "a", and the condition "b.y=1"
* can be pushed down to "b". That means it is possible to use an index in
* this case.
*
* @param s the selector
*/
public abstract void restrictPushDown(SelectorImpl s);
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (!(other instanceof ConstraintImpl)) {
return false;
}
return toString().equals(other.toString());
}
@Override
public int hashCode() {
return toString().hashCode();
}
/**
* Whether the constraint contains a fulltext condition that requires
* using a fulltext index, because the condition can only be evaluated there.
*
* @return true if yes
*/
public boolean requiresFullTextIndex() {
return false;
}
/**
* Whether the condition contains a fulltext condition that can not be
* applied to the filter, for example because it is part of an "or" condition
* of the form "where a=1 or contains(., 'x')".
*
* @return true if yes
*/
public boolean containsUnfilteredFullTextCondition() {
return false;
}
/**
* Compute a set of sub-constraints that could be used for composing UNION
* statements. For example in case of "c=1 or c=2", it will return to the
* caller {@code [c=1, c=2]}. Those can be later on used for re-composing
* conditions.
* <p>
* If it is not possible to convert to a union, it must return an empty set.
* <p>
* The default implementation in {@link ConstraintImpl#convertToUnion()}
* always return an empty set.
*
* @return the set of union constraints, if available, or an empty set if
* conversion is not possible
*/
@NotNull
public Set<ConstraintImpl> convertToUnion() {
return Collections.emptySet();
}
}