tech.ydb.yoj.repository.db.TableQueryBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yoj-repository Show documentation
Show all versions of yoj-repository Show documentation
Core YOJ (YDB ORM for Java) abstractions and APIs for domain entities, repositories, transactions etc.
package tech.ydb.yoj.repository.db;
import com.google.common.base.Preconditions;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import tech.ydb.yoj.databind.expression.FilterBuilder;
import tech.ydb.yoj.databind.expression.FilterExpression;
import tech.ydb.yoj.databind.expression.OrderBuilder;
import tech.ydb.yoj.databind.expression.OrderExpression;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.UnaryOperator;
import static lombok.AccessLevel.PRIVATE;
public final class TableQueryBuilder> {
private final Table table;
private Set extends Entity.Id> ids;
private Set> keys;
private String indexName = null;
private Integer limit = null;
private Long offset = null;
private FilterExpression filter = null;
private FilterBuilder filterBuilder = null;
private OrderExpression orderBy = null;
public TableQueryBuilder(@NonNull Table table) {
this.table = table;
}
public long count() {
Preconditions.checkState(ids == null && keys == null, "Count query doesn't support selecting by ids/keys");
FilterExpression filter = getFinalFilter();
if (filter == null) {
return table.countAll();
}
return table.count(indexName, filter);
}
public boolean exists() {
return findOne() != null;
}
@Nullable
public T findOne() {
List results = find(1);
return results.isEmpty() ? null : results.get(0);
}
@Nullable
public V findOne(Class viewClass) {
List results = limit(1).find(viewClass, false);
return results.isEmpty() ? null : results.get(0);
}
@NonNull
public List find() {
return find(limit);
}
@NonNull
public List find(Class viewClass) {
return find(viewClass, false);
}
private List find(Integer limit) {
if (ids == null && keys == null) {
return table.find(indexName, getFinalFilter(), orderBy, limit, offset);
}
Preconditions.checkState(offset == null, "Query selecting by ids/keys does not support offset");
if (ids != null) {
Preconditions.checkState(indexName == null, "Query searching by ids must use PK but the secondary index is specified");
return table.find(ids, getFinalFilter(), orderBy, limit);
} else {
Preconditions.checkState(indexName != null, "Query searching by arbitrary keys requires an appropriate index");
return table.find(indexName, keys, getFinalFilter(), orderBy, limit);
}
}
public List find(Class viewClass, boolean distinct) {
if (ids == null && keys == null) {
return table.find(viewClass, indexName, getFinalFilter(), orderBy, limit, offset, distinct);
}
Preconditions.checkState(!distinct, "Query searching by ids/keys does not support distinct");
Preconditions.checkState(offset == null, "Query searching by ids/keys does not support offset");
if (ids != null) {
Preconditions.checkState(indexName == null, "Query searching by ids must use PK but the secondary index is specified");
return table.find(viewClass, ids, getFinalFilter(), orderBy, limit);
} else {
Preconditions.checkState(indexName != null, "Query searching by arbitrary keys requires an appropriate index");
return table.find(viewClass, indexName, keys, getFinalFilter(), orderBy, limit);
}
}
@NonNull
public > List findIds() {
return table.findIds(indexName, getFinalFilter(), orderBy, limit, offset);
}
@NonNull
public > TableQueryBuilder ids(Set ids) {
Preconditions.checkState(keys == null, "You can't use both .ids and .keys methods");
this.ids = ids;
return this;
}
@NonNull
public TableQueryBuilder keys(Set> keys) {
Preconditions.checkState(ids == null, "You can't use both .keys and .ids methods");
this.keys = keys;
return this;
}
@NonNull
public TableQueryFieldFilterBuilder where(@NonNull String fieldPath) {
return new TableQueryFieldFilterBuilder(filterBuilder().where(fieldPath));
}
@NonNull
public TableQueryBuilder where(@NonNull UnaryOperator> filterBuilderOp) {
return where(buildFilterExpression(filterBuilderOp));
}
@NonNull
public TableQueryBuilder where(@NonNull FilterExpression filter) {
filterBuilder = filterBuilder().where(filter);
return this;
}
private FilterBuilder filterBuilder() {
if (filterBuilder == null) {
Preconditions.checkState(filter == null, "You can't use both .where/.and/.or and .filter methods");
filterBuilder = EntityExpressions.newFilterBuilder(table.getType());
}
return filterBuilder;
}
@NonNull
public TableQueryFieldFilterBuilder and(@NonNull String fieldPath) {
return new TableQueryFieldFilterBuilder(filterBuilder().and(fieldPath));
}
@NonNull
public TableQueryBuilder and(@Nullable FilterExpression filter) {
filterBuilder = filterBuilder().and(filter);
return this;
}
@NonNull
public TableQueryBuilder and(@NonNull UnaryOperator> filterBuilderOp) {
return and(buildFilterExpression(filterBuilderOp));
}
@NonNull
public TableQueryFieldFilterBuilder or(@NonNull String fieldPath) {
return new TableQueryFieldFilterBuilder(filterBuilder().or(fieldPath));
}
@NonNull
public TableQueryBuilder or(@NonNull FilterExpression filter) {
filterBuilder = filterBuilder().or(filter);
return this;
}
@NonNull
public TableQueryBuilder or(@NonNull UnaryOperator> filterBuilderOp) {
return or(buildFilterExpression(filterBuilderOp));
}
@Nullable
private FilterExpression getFinalFilter() {
if (filter != null) {
return filter;
} else if (filterBuilder != null) {
return filterBuilder.build();
} else {
return null;
}
}
@NonNull
public TableQueryBuilder orderBy(@Nullable OrderExpression orderBy) {
this.orderBy = orderBy;
return this;
}
@NonNull
public TableQueryBuilder orderBy(@NonNull UnaryOperator> orderBuilderOp) {
return orderBy(orderBuilderOp.apply(EntityExpressions.newOrderBuilder(table.getType())).build());
}
public TableQueryBuilder defaultOrder() {
orderBy = EntityExpressions.defaultOrder(table.getType());
return this;
}
@NonNull
public TableQueryBuilder filter(@Nullable FilterExpression filter) {
Preconditions.checkState(filterBuilder == null, "You can't use both .filter and .where/.and/.or methods");
this.filter = filter;
return this;
}
@NonNull
public TableQueryBuilder filter(@NonNull UnaryOperator> filterBuilderOp) {
return filter(buildFilterExpression(filterBuilderOp));
}
@NonNull
public TableQueryBuilder offset(long offset) {
this.offset = offset;
return this;
}
@NonNull
public TableQueryBuilder limit(long limit) {
Preconditions.checkArgument(limit > 0, "'limit' must be greater than zero");
this.limit = Math.toIntExact(limit);
return this;
}
@NonNull
public TableQueryBuilder index(String indexName) {
this.indexName = indexName;
return this;
}
private FilterExpression buildFilterExpression(UnaryOperator> filterBuilderOp) {
return filterBuilderOp.apply(EntityExpressions.newFilterBuilder(table.getType())).build();
}
@RequiredArgsConstructor(access = PRIVATE)
public class TableQueryFieldFilterBuilder {
@NonNull
private final FilterBuilder.FieldBuilder fieldBuilder;
@NonNull
@SafeVarargs
public final TableQueryBuilder in(@NonNull V possibleValue, @NonNull V... otherPossibleValues) {
filterBuilder = fieldBuilder.in(possibleValue, otherPossibleValues);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder in(@NonNull Collection<@NonNull ? extends V> values) {
filterBuilder = fieldBuilder.in(values);
return TableQueryBuilder.this;
}
@NonNull
@SafeVarargs
public final TableQueryBuilder notIn(@NonNull V impossibleValue, @NonNull V... otherImpossibleValues) {
filterBuilder = fieldBuilder.notIn(impossibleValue, otherImpossibleValues);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder notIn(@NonNull Collection<@NonNull ? extends V> values) {
filterBuilder = fieldBuilder.notIn(values);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder eq(@Nullable Object value) {
filterBuilder = fieldBuilder.eq(value);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder neq(@Nullable Object value) {
filterBuilder = fieldBuilder.neq(value);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder lt(@NonNull Object value) {
filterBuilder = fieldBuilder.lt(value);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder lte(@NonNull Object value) {
filterBuilder = fieldBuilder.lte(value);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder gt(@NonNull Object value) {
filterBuilder = fieldBuilder.gt(value);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder gte(@NonNull Object value) {
filterBuilder = fieldBuilder.gte(value);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder between(@NonNull Object min, @NonNull Object max) {
filterBuilder = fieldBuilder.between(min, max);
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder isNull() {
filterBuilder = fieldBuilder.isNull();
return TableQueryBuilder.this;
}
@NonNull
public TableQueryBuilder isNotNull() {
filterBuilder = fieldBuilder.isNotNull();
return TableQueryBuilder.this;
}
}
}