| /* |
| * 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.cassandra.cql3.restrictions; |
| |
| import java.util.List; |
| |
| import org.apache.cassandra.config.ColumnDefinition; |
| import org.apache.cassandra.cql3.Operator; |
| import org.apache.cassandra.cql3.Term; |
| import org.apache.cassandra.cql3.functions.Function; |
| import org.apache.cassandra.cql3.statements.Bound; |
| import org.apache.cassandra.index.Index; |
| |
| public final class TermSlice |
| { |
| /** |
| * The slice boundaries. |
| */ |
| private final Term[] bounds; |
| |
| /** |
| * Specifies if a slice boundary is inclusive or not. |
| */ |
| private final boolean[] boundInclusive; |
| |
| /** |
| * Creates a new <code>TermSlice</code> with the specified boundaries. |
| * |
| * @param start the lower boundary |
| * @param includeStart <code>true</code> if the lower boundary is inclusive |
| * @param end the upper boundary |
| * @param includeEnd <code>true</code> if the upper boundary is inclusive |
| */ |
| private TermSlice(Term start, boolean includeStart, Term end, boolean includeEnd) |
| { |
| bounds = new Term[]{start, end}; |
| boundInclusive = new boolean[]{includeStart, includeEnd}; |
| } |
| |
| /** |
| * Creates a new <code>TermSlice</code> with the specified boundary. |
| * |
| * @param bound the boundary type |
| * @param include <code>true</code> if the boundary is inclusive |
| * @param term the value |
| * @return a new <code>TermSlice</code> instance |
| */ |
| public static TermSlice newInstance(Bound bound, boolean include, Term term) |
| { |
| return bound.isStart() ? new TermSlice(term, include, null, false) |
| : new TermSlice(null, false, term, include); |
| } |
| |
| /** |
| * Returns the boundary value. |
| * |
| * @param bound the boundary type |
| * @return the boundary value |
| */ |
| public Term bound(Bound bound) |
| { |
| return bounds[bound.idx]; |
| } |
| |
| /** |
| * Checks if this slice has a boundary for the specified type. |
| * |
| * @param b the boundary type |
| * @return <code>true</code> if this slice has a boundary for the specified type, <code>false</code> otherwise. |
| */ |
| public boolean hasBound(Bound b) |
| { |
| return bounds[b.idx] != null; |
| } |
| |
| /** |
| * Checks if this slice boundary is inclusive for the specified type. |
| * |
| * @param b the boundary type |
| * @return <code>true</code> if this slice boundary is inclusive for the specified type, |
| * <code>false</code> otherwise. |
| */ |
| public boolean isInclusive(Bound b) |
| { |
| return bounds[b.idx] == null || boundInclusive[b.idx]; |
| } |
| |
| /** |
| * Merges this slice with the specified one. |
| * |
| * @param otherSlice the slice to merge to |
| * @return the new slice resulting from the merge |
| */ |
| public TermSlice merge(TermSlice otherSlice) |
| { |
| if (hasBound(Bound.START)) |
| { |
| assert !otherSlice.hasBound(Bound.START); |
| |
| return new TermSlice(bound(Bound.START), |
| isInclusive(Bound.START), |
| otherSlice.bound(Bound.END), |
| otherSlice.isInclusive(Bound.END)); |
| } |
| assert !otherSlice.hasBound(Bound.END); |
| |
| return new TermSlice(otherSlice.bound(Bound.START), |
| otherSlice.isInclusive(Bound.START), |
| bound(Bound.END), |
| isInclusive(Bound.END)); |
| } |
| |
| @Override |
| public String toString() |
| { |
| return String.format("(%s %s, %s %s)", boundInclusive[0] ? ">=" : ">", |
| bounds[0], |
| boundInclusive[1] ? "<=" : "<", |
| bounds[1]); |
| } |
| |
| /** |
| * Returns the index operator corresponding to the specified boundary. |
| * |
| * @param b the boundary type |
| * @return the index operator corresponding to the specified boundary |
| */ |
| public Operator getIndexOperator(Bound b) |
| { |
| if (b.isStart()) |
| return boundInclusive[b.idx] ? Operator.GTE : Operator.GT; |
| |
| return boundInclusive[b.idx] ? Operator.LTE : Operator.LT; |
| } |
| |
| /** |
| * Check if this <code>TermSlice</code> is supported by the specified index. |
| * |
| * @param index the secondary index |
| * @return <code>true</code> this type of <code>TermSlice</code> is supported by the specified index, |
| * <code>false</code> otherwise. |
| */ |
| public boolean isSupportedBy(ColumnDefinition column, Index index) |
| { |
| boolean supported = false; |
| |
| if (hasBound(Bound.START)) |
| supported |= isInclusive(Bound.START) ? index.supportsExpression(column, Operator.GTE) |
| : index.supportsExpression(column, Operator.GT); |
| if (hasBound(Bound.END)) |
| supported |= isInclusive(Bound.END) ? index.supportsExpression(column, Operator.LTE) |
| : index.supportsExpression(column, Operator.LT); |
| |
| return supported; |
| } |
| |
| public void addFunctionsTo(List<Function> functions) |
| { |
| if (hasBound(Bound.START)) |
| bound(Bound.START).addFunctionsTo(functions); |
| |
| if (hasBound(Bound.END)) |
| bound(Bound.END).addFunctionsTo(functions); |
| } |
| } |