All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.e6tech.elements.cassandra.query.RangeQuery Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2015-2020 Futeh Kao
 *
 * Licensed 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 net.e6tech.elements.cassandra.query;

import net.e6tech.elements.cassandra.Sibyl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

/**
 * Range query is used to query a range, e.g. creationTime >= x and createTime < y order by creationTime asc.  Keep in
 * mind the inclusion of end points depends on the order by.  Using the previous example, if we were to change it to descending
 * order, the query would look like creationTime > x and createTime <= y order by creationTime desc.
 *
 * The query does its best to limit the result set to the limit size.  In some cases, it may return a list that is slightly larger
 * than the limit size.  This could happen for example when multiple records of the same creationTime span the page boundary.
 *
 * 
 * 
 * RangeQuery<X> query = new RangeQuery<>(sibyl, X.class);
 * query.partition(X::setPartitionKey, 1L)
 *      .descending(X::setCreationTime, 0L, 9999999999999L)
 *      .limit(50);
 * 
 * 
* * @param entity table type */ public class RangeQuery extends BaseQuery> { private boolean subQuery; public RangeQuery(Sibyl sibyl, Class entityClass) { super(sibyl, entityClass); } public List query() { validate(); List list = select(); return patchBoundary(list); } private List patchBoundary(List list) { if (!subQuery && !orderBy.isEmpty() && list.size() == limit && limit > 0) { T last = list.get(list.size() - 1); RangeQuery sub = subQuery(last); return merge(list, sub.query(), last); } return list; } private RangeQuery subQuery(T last) { RangeQuery sub = new RangeQuery<>(sibyl, entityClass); sub.subQuery = true; sub.partitionRelations = new ArrayList<>(partitionRelations); // get a list of order by columns. use them to filter remove last few potentially same entries Set set = new HashSet<>(); Consumer consumer = r -> { if (set.contains(r.keyColumn.getName())) return; Relation subR = new Relation(r.keyColumn, Comparison.EQUAL, r.value); sub.clusteringRelations.add(subR); set.add(r.keyColumn.getName()); }; clusteringRelations.forEach(consumer); orderBy.forEach(consumer); for (Relation r : sub.clusteringRelations) { r.value = r.accessor.get(last); } return sub; } private List merge(List list, List list2, T last) { int trimLast = list.size(); for (int i = list.size() - 1; i >= 0; i --) { T t = list.get(i); boolean same = true; for (Relation relation : orderBy) { if (!relation.isRelated(last, t)) { same = false; break; } } if (!same) break; trimLast = i; } list = list.subList(0, trimLast); list.addAll(list2); return list; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy