Search in sources :

Example 1 with Keyset

use of com.blazebit.persistence.Keyset in project blaze-persistence by Blazebit.

the class KeysetManager method buildOptimizedKeysetPredicate.

public void buildOptimizedKeysetPredicate(StringBuilder sb, int positionalOffset) {
    KeysetLink keysetLink = getKeysetLink();
    KeysetMode keysetMode = keysetLink.getKeysetMode();
    Keyset keyset = keysetLink.getKeyset();
    Serializable[] key = keyset.getTuple();
    OrderByExpression extractedNonNullableExpression = null;
    if (key != null) {
        boolean hasNullableOrderBys = false;
        // TODO: Determine if order by expression has parameter as that will ruin reordering of expressions in row value constructor
        boolean hasParameterInOrderBy = false;
        for (OrderByExpression orderByExpression : orderByExpressions) {
            if (orderByExpression.isNullable()) {
                hasNullableOrderBys = true;
                break;
            }
        }
        extractedNonNullableExpression = orderByExpressions.get(0);
        // if all order bys are non-nullable because null elements would break the row value comparison.
        if (hasNullableOrderBys || hasParameterInOrderBy || !dbmsDialect.supportsFullRowValueComparison() || !jpaProvider.supportsCustomFunctions()) {
            // Under certain conditions, we cannot render an optimized form because we would need to include
            // null checks involving disjunction on the top predicate level which would contradict the main idea of the
            // optimization.
            boolean optimizationAllowed = !extractedNonNullableExpression.isNullable() || keysetMode == KeysetMode.NEXT && extractedNonNullableExpression.isNullFirst() && key[0] != null || keysetMode == KeysetMode.PREVIOUS && !extractedNonNullableExpression.isNullFirst() && key[0] != null;
            if (optimizationAllowed) {
                applyOptimizedKeysetNotNullItem(extractedNonNullableExpression, sb, 0, key[0], keysetMode, false, positionalOffset);
                if (orderByExpressions.size() > 1) {
                    sb.append(" AND NOT (");
                    applyKeysetItem(sb, extractedNonNullableExpression.getExpression(), "=", 0, key[0], positionalOffset);
                    sb.append(" AND ");
                    buildOptimizedPredicate0(keysetMode, key, sb, orderByExpressions, positionalOffset);
                    sb.append(")");
                }
            } else {
                buildKeysetPredicate0(keysetMode, key, sb, orderByExpressions, positionalOffset);
            }
        } else {
            // we can use row value constructor syntax
            // the rendering is heavily bound to the way this is parsed in RowValueComparisonFunction
            queryGenerator.setClauseType(ClauseType.WHERE);
            queryGenerator.setQueryBuffer(sb);
            queryGenerator.setClauseType(null);
            sb.append(jpaProvider.getCustomFunctionInvocation(RowValueComparisonFunction.FUNCTION_NAME, 1)).append('\'').append(keysetMode == KeysetMode.SAME ? "<=" : "<").append('\'');
            for (int i = 0; i < orderByExpressions.size(); i++) {
                OrderByExpression orderByExpression = orderByExpressions.get(i);
                sb.append(",CASE WHEN (1=NULLIF(1,1) AND ");
                if (orderByExpression.isDescending() && keysetMode != KeysetMode.PREVIOUS || orderByExpression.isAscending() && keysetMode == KeysetMode.PREVIOUS) {
                    // Placeholder is needed as we need to render the parameter at the end to retain JDBC parameter order
                    sb.append("1=NULLIF(1,1)");
                } else {
                    applyKeysetParameter(sb, i, key[i], positionalOffset);
                    sb.append('=');
                    queryGenerator.generate(orderByExpression.getExpression());
                }
                sb.append(") THEN 1 ELSE 0 END");
            }
            // We have to render right hand side parameters at the end to retain the correct order
            for (int i = 0; i < orderByExpressions.size(); i++) {
                OrderByExpression orderByExpression = orderByExpressions.get(i);
                if (orderByExpression.isDescending() && keysetMode != KeysetMode.PREVIOUS || orderByExpression.isAscending() && keysetMode == KeysetMode.PREVIOUS) {
                    sb.append(",CASE WHEN (1=NULLIF(1,1) AND ");
                    queryGenerator.generate(orderByExpression.getExpression());
                    sb.append('=');
                    applyKeysetParameter(sb, i, key[i], positionalOffset);
                    sb.append(") THEN 1 ELSE 0 END");
                }
            }
            sb.append(") = 0");
        }
    }
}
Also used : Keyset(com.blazebit.persistence.Keyset) Serializable(java.io.Serializable) OrderByExpression(com.blazebit.persistence.impl.OrderByExpression)

Example 2 with Keyset

use of com.blazebit.persistence.Keyset 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);
}
Also used : Keyset(com.blazebit.persistence.Keyset) DefaultKeyset(com.blazebit.persistence.DefaultKeyset) PagedList(com.blazebit.persistence.PagedList) ArrayList(java.util.ArrayList) KeysetPage(com.blazebit.persistence.KeysetPage) DefaultKeysetPage(com.blazebit.persistence.DefaultKeysetPage) PageInfo(graphql.relay.PageInfo) DefaultPageInfo(graphql.relay.DefaultPageInfo) DefaultConnection(graphql.relay.DefaultConnection) DefaultEdge(graphql.relay.DefaultEdge) Edge(graphql.relay.Edge) DefaultPageInfo(graphql.relay.DefaultPageInfo) DefaultConnectionCursor(graphql.relay.DefaultConnectionCursor)

Example 3 with Keyset

use of com.blazebit.persistence.Keyset in project blaze-persistence by Blazebit.

the class KeysetManager method buildKeysetPredicate.

public void buildKeysetPredicate(StringBuilder sb, int positionalOffset) {
    KeysetLink keysetLink = getKeysetLink();
    KeysetMode keysetMode = keysetLink.getKeysetMode();
    Keyset keyset = keysetLink.getKeyset();
    Serializable[] key = keyset.getTuple();
    if (key != null) {
        buildKeysetPredicate0(keysetMode, key, sb, orderByExpressions, positionalOffset);
    }
}
Also used : Keyset(com.blazebit.persistence.Keyset) Serializable(java.io.Serializable)

Aggregations

Keyset (com.blazebit.persistence.Keyset)3 Serializable (java.io.Serializable)2 DefaultKeyset (com.blazebit.persistence.DefaultKeyset)1 DefaultKeysetPage (com.blazebit.persistence.DefaultKeysetPage)1 KeysetPage (com.blazebit.persistence.KeysetPage)1 PagedList (com.blazebit.persistence.PagedList)1 OrderByExpression (com.blazebit.persistence.impl.OrderByExpression)1 DefaultConnection (graphql.relay.DefaultConnection)1 DefaultConnectionCursor (graphql.relay.DefaultConnectionCursor)1 DefaultEdge (graphql.relay.DefaultEdge)1 DefaultPageInfo (graphql.relay.DefaultPageInfo)1 Edge (graphql.relay.Edge)1 PageInfo (graphql.relay.PageInfo)1 ArrayList (java.util.ArrayList)1