use of com.blazebit.persistence.PagedList in project blaze-persistence by Blazebit.
the class PaginatedTypedQueryImpl method getResultList.
private PagedList<X> getResultList(int queryFirstResult, int firstRow, long totalSize) {
if (idQuery != null) {
idQuery.setMaxResults(pageSize);
if (forceFirstResult || keysetMode == KeysetMode.NONE) {
idQuery.setFirstResult(firstRow);
} else {
idQuery.setFirstResult(0);
}
List<?> ids = idQuery.getResultList();
if (ids.isEmpty()) {
KeysetPage newKeysetPage = null;
if (keysetMode == KeysetMode.NEXT) {
// When we scroll over the last page to a non existing one, we reuse the current keyset
newKeysetPage = keysetPage;
}
long size;
if (withCount && totalSize == -1) {
size = getTotalCount();
} else {
size = totalSize;
}
if (boundedCount) {
if (keysetMode == KeysetMode.NEXT) {
size = Math.max(size, keysetPage.getFirstResult() + keysetPage.getMaxResults());
} else if (forceFirstResult || keysetMode == KeysetMode.NONE) {
size = Math.max(size, firstRow);
}
}
return new PagedArrayList<X>(newKeysetPage, size, queryFirstResult, pageSize);
}
Serializable[] lowest = null;
Serializable[] highest = null;
Serializable[][] keysets = null;
if (needsNewIdList) {
if (keysetToSelectIndexMapping != null) {
int keysetPageSize = pageSize - highestOffset;
int size = Math.min(ids.size(), keysetPageSize);
int lowestIndex;
int highestIndex;
// Swap keysets as we have inverse ordering when going to the previous page
if (keysetMode == KeysetMode.PREVIOUS) {
lowestIndex = size - 1;
highestIndex = 0;
} else {
lowestIndex = 0;
highestIndex = size - 1;
}
if (ids.get(0) instanceof Object[]) {
if (withExtractAllKeysets) {
keysets = new Serializable[size][];
for (int i = 0; i < size; i++) {
keysets[i] = KeysetPaginationHelper.extractKey((Object[]) ids.get(i), keysetToSelectIndexMapping, keysetSuffix);
}
lowest = keysets[lowestIndex];
highest = keysets[highestIndex];
} else {
lowest = KeysetPaginationHelper.extractKey((Object[]) ids.get(lowestIndex), keysetToSelectIndexMapping, keysetSuffix);
highest = KeysetPaginationHelper.extractKey((Object[]) ids.get(highestIndex), keysetToSelectIndexMapping, keysetSuffix);
}
} else {
if (withExtractAllKeysets) {
keysets = new Serializable[size][];
for (int i = 0; i < size; i++) {
keysets[i] = new Serializable[] { (Serializable) (ids.get(i)) };
}
lowest = keysets[lowestIndex];
highest = keysets[highestIndex];
} else {
lowest = new Serializable[] { (Serializable) ids.get(lowestIndex) };
highest = new Serializable[] { (Serializable) ids.get(highestIndex) };
}
}
// Swap keysets as we have inverse ordering when going to the previous page
if (keysetMode == KeysetMode.PREVIOUS) {
if (withExtractAllKeysets) {
// Reverse the keysets
Serializable[] tmp;
for (int i = 0, mid = size >> 1, j = size - 1; i < mid; i++, j--) {
tmp = keysets[i];
keysets[i] = keysets[j];
keysets[j] = tmp;
}
}
}
}
// extract count
if (inlinedCountQuery) {
Object[] first = (Object[]) ids.get(0);
totalSize = (long) first[first.length - 1];
}
List<Object> newIds = new ArrayList<Object>(ids.size());
if (identifierCount > 1) {
for (int i = 0; i < ids.size(); i++) {
Object[] tuple = (Object[]) ids.get(i);
Object newId = new Object[identifierCount];
System.arraycopy(tuple, 0, newId, 0, identifierCount);
newIds.add(newId);
}
} else {
for (int i = 0; i < ids.size(); i++) {
Object o = ids.get(i);
if (o instanceof Object[]) {
newIds.add(((Object[]) o)[0]);
} else {
newIds.add(o);
}
}
}
ids = newIds;
} else if (inlinedCountQuery) {
Object[] first = (Object[]) ids.get(0);
int newSize = first.length - 1;
totalSize = (long) first[first.length - 1];
// If this would have been a non-object array type without the count query, we must unwrap the result
List<Object> newIds = new ArrayList<>(ids.size());
if (newSize == 1) {
for (int i = 0; i < ids.size(); i++) {
newIds.add(((Object[]) ids.get(i))[0]);
}
} else {
for (int i = 0; i < ids.size(); i++) {
Object[] tuple = (Object[]) ids.get(i);
Object newId = new Object[newSize];
System.arraycopy(tuple, 0, newId, 0, newSize);
newIds.add(newId);
}
}
ids = newIds;
}
if (identifierCount > 1) {
StringBuilder parameterNameBuilder = new StringBuilder(AbstractCommonQueryBuilder.ID_PARAM_NAME.length() + 10);
parameterNameBuilder.append(AbstractCommonQueryBuilder.ID_PARAM_NAME).append('_');
int start = parameterNameBuilder.length();
Object[] empty = ids.size() < pageSize ? new Object[identifierCount] : null;
for (int i = 0; i < pageSize; i++) {
Object[] tuple;
if (ids.size() > i) {
tuple = (Object[]) ids.get(i);
} else {
tuple = empty;
}
for (int j = 0; j < identifierCount; j++) {
parameterNameBuilder.setLength(start);
parameterNameBuilder.append(j).append('_').append(i);
objectQuery.setParameter(parameterNameBuilder.toString(), tuple[j]);
}
}
} else {
objectQuery.setParameter(AbstractCommonQueryBuilder.ID_PARAM_NAME, ids);
}
KeysetPage newKeyset = null;
if (keysetToSelectIndexMapping != null) {
newKeyset = new DefaultKeysetPage(firstRow, pageSize, lowest, highest, keysets);
}
totalSize = Math.max(totalSize, firstRow + ids.size());
List<X> queryResultList = objectQuery.getResultList();
PagedList<X> pagedResultList = new PagedArrayList<X>(queryResultList, newKeyset, totalSize, queryFirstResult, pageSize);
return pagedResultList;
} else {
if (!inlinedIdQuery) {
objectQuery.setMaxResults(pageSize);
if (forceFirstResult || keysetMode == KeysetMode.NONE) {
objectQuery.setFirstResult(firstRow);
} else {
objectQuery.setFirstResult(0);
}
}
List<X> result = objectQuery.getResultList();
if (result.isEmpty()) {
KeysetPage newKeysetPage = null;
if (keysetMode == KeysetMode.NEXT) {
// When we scroll over the last page to a non existing one, we reuse the current keyset
newKeysetPage = keysetPage;
}
if (totalSize == -1) {
if (inlinedCountQuery && firstRow == 0) {
totalSize = 0L;
} else if (withCount) {
totalSize = getTotalCount();
}
}
if (boundedCount) {
if (keysetMode == KeysetMode.NEXT) {
totalSize = Math.max(totalSize, keysetPage.getFirstResult() + keysetPage.getMaxResults());
} else if (forceFirstResult || keysetMode == KeysetMode.NONE) {
totalSize = Math.max(totalSize, firstRow);
}
}
return new PagedArrayList<X>(newKeysetPage, totalSize, queryFirstResult, pageSize);
}
if (keysetMode == KeysetMode.PREVIOUS) {
Collections.reverse(result);
}
KeysetPage newKeyset = null;
if (keysetToSelectIndexMapping != null) {
if (objectBuilder == null) {
// extract count
if (inlinedCountQuery) {
Object[] first = (Object[]) result.get(0);
totalSize = (long) first[first.length - 1];
// If this would have been a non-object array type without the count query, we must unwrap the result
if (first.length == 2) {
List<X> newResult = new ArrayList<>(result.size());
for (int i = 0; i < result.size(); i++) {
newResult.add((X) ((Object[]) result.get(i))[0]);
}
result = newResult;
}
}
} else if (objectBuilder instanceof KeysetExtractionObjectBuilder<?>) {
KeysetExtractionObjectBuilder<?> keysetExtractionObjectBuilder = (KeysetExtractionObjectBuilder<?>) objectBuilder;
Serializable[] lowest = keysetExtractionObjectBuilder.getLowest();
Serializable[] highest = keysetExtractionObjectBuilder.getHighest();
Serializable[][] keysets = keysetExtractionObjectBuilder.getKeysets();
// extract count
if (inlinedCountQuery) {
totalSize = keysetExtractionObjectBuilder.getCount();
}
newKeyset = new DefaultKeysetPage(firstRow, pageSize, lowest, highest, keysets);
} else if (objectBuilder instanceof CountExtractionObjectBuilder<?>) {
totalSize = ((CountExtractionObjectBuilder<X>) objectBuilder).getCount();
}
}
totalSize = Math.max(totalSize, firstRow + result.size());
PagedList<X> pagedResultList = new PagedArrayList<X>(result, newKeyset, totalSize, queryFirstResult, pageSize);
return pagedResultList;
}
}
use of com.blazebit.persistence.PagedList in project blaze-persistence by Blazebit.
the class OptimizedKeysetPaginationRowValueConstructorTest method keysetPaginationWithSimpleObjectQueryTest.
@Test
public void keysetPaginationWithSimpleObjectQueryTest() {
KeysetPage keyset = null;
PaginatedCriteriaBuilder<String> crit = cbf.create(em, String.class).from(Document.class, "d").orderByAsc("d.id").selectNew(new ObjectBuilder<String>() {
@Override
public <X extends SelectBuilder<X>> void applySelects(X selectBuilder) {
selectBuilder.select("d.name").select("d.owner.name");
}
@Override
public String build(Object[] tuple) {
return tuple[0] + " - " + tuple[1];
}
@Override
public List<String> buildList(List<String> list) {
return list;
}
}).page(keyset, 0, 1);
PagedList<String> result = crit.getResultList();
assertEquals(1, result.size());
assertEquals("doc1 - Karl1", result.get(0));
keyset = result.getKeysetPage();
crit = crit.page(keyset, 1, 1);
result = crit.getResultList();
assertEquals(1, result.size());
assertEquals("doc2 - Karl2", result.get(0));
}
use of com.blazebit.persistence.PagedList in project blaze-persistence by Blazebit.
the class OptimizedKeysetPaginationTest method keysetPaginationWithSimpleObjectQueryTest.
@Test
public void keysetPaginationWithSimpleObjectQueryTest() {
KeysetPage keyset = null;
PaginatedCriteriaBuilder<String> crit = cbf.create(em, String.class).from(DocumentWithNullableName.class, "d").orderByAsc("d.id").selectNew(new ObjectBuilder<String>() {
@Override
public <X extends SelectBuilder<X>> void applySelects(X selectBuilder) {
selectBuilder.select("d.name").select("d.owner.name");
}
@Override
public String build(Object[] tuple) {
return tuple[0] + " - " + tuple[1];
}
@Override
public List<String> buildList(List<String> list) {
return list;
}
}).page(keyset, 0, 1);
PagedList<String> result = crit.getResultList();
assertEquals(1, result.size());
assertEquals("doc1 - Karl1", result.get(0));
keyset = result.getKeysetPage();
crit = crit.page(keyset, 1, 1);
result = crit.getResultList();
assertEquals(1, result.size());
assertEquals("doc2 - Karl2", result.get(0));
}
use of com.blazebit.persistence.PagedList in project blaze-persistence by Blazebit.
the class KeysetPaginationTest method keysetPaginationWithSimpleObjectQueryTest.
@Test
public void keysetPaginationWithSimpleObjectQueryTest() {
KeysetPage keyset = null;
PaginatedCriteriaBuilder<String> crit = cbf.create(em, String.class).from(Document.class, "d").orderByAsc("d.id").selectNew(new ObjectBuilder<String>() {
@Override
public <X extends SelectBuilder<X>> void applySelects(X selectBuilder) {
selectBuilder.select("d.name").select("d.owner.name");
}
@Override
public String build(Object[] tuple) {
return tuple[0] + " - " + tuple[1];
}
@Override
public List<String> buildList(List<String> list) {
return list;
}
}).page(keyset, 0, 1);
PagedList<String> result = crit.getResultList();
assertEquals(1, result.size());
assertEquals("doc1 - Karl1", result.get(0));
keyset = result.getKeysetPage();
crit = crit.page(keyset, 1, 1);
result = crit.getResultList();
assertEquals(1, result.size());
assertEquals("doc2 - Karl2", result.get(0));
}
use of com.blazebit.persistence.PagedList in project blaze-persistence by Blazebit.
the class GraphQLEntityViewSupport method createRelayConnection.
/**
* Returns a relay connection from the given result list.
*
* @param list the result list
* @return the relay connection
*/
public <T> Connection<T> createRelayConnection(List<T> list) {
List<Edge<T>> edges = new ArrayList<>(list.size());
boolean hasPreviousPage;
boolean hasNextPage;
KeysetPage keysetPage;
if (list instanceof PagedList<?>) {
PagedList<T> data = (PagedList<T>) list;
hasPreviousPage = data.getFirstResult() != 0;
hasNextPage = data.getTotalSize() == -1 || data.getFirstResult() + data.getMaxResults() < data.getTotalSize();
keysetPage = data.getKeysetPage();
} else {
hasPreviousPage = true;
hasNextPage = true;
keysetPage = null;
}
if (keysetPage == null) {
for (int i = 0; i < list.size(); i++) {
edges.add(new DefaultEdge<>(list.get(i), new DefaultConnectionCursor(Integer.toString(i + 1))));
}
} else {
PagedList<T> data = (PagedList<T>) list;
List<Keyset> keysets = keysetPage.getKeysets();
int listSize = list.size();
if (listSize != 0 && keysets.size() != listSize) {
int end = listSize - 1;
edges.add(new DefaultEdge<>(list.get(0), new DefaultConnectionCursor(Base64.getEncoder().encodeToString(serializeCursor(data.getFirstResult(), data.getMaxResults(), keysetPage.getLowest().getTuple())))));
for (int i = 1; i < end; i++) {
T node = list.get(i);
edges.add(new DefaultEdge<>(node, new DefaultConnectionCursor(Integer.toString(i + 1))));
}
edges.add(new DefaultEdge<>(list.get(end), new DefaultConnectionCursor(Base64.getEncoder().encodeToString(serializeCursor(data.getFirstResult(), data.getMaxResults(), keysetPage.getHighest().getTuple())))));
} else {
for (int i = 0; i < list.size(); i++) {
T node = list.get(i);
edges.add(new DefaultEdge<>(node, new DefaultConnectionCursor(Base64.getEncoder().encodeToString(serializeCursor(data.getFirstResult(), data.getMaxResults(), keysets.get(i).getTuple())))));
}
}
}
PageInfo pageInfo;
if (edges.isEmpty()) {
pageInfo = new DefaultPageInfo(null, null, hasPreviousPage, hasNextPage);
} else {
pageInfo = new DefaultPageInfo(edges.get(0).getCursor(), edges.get(edges.size() - 1).getCursor(), hasPreviousPage, hasNextPage);
}
return new DefaultConnection<>(edges, pageInfo);
}
Aggregations