io.katharsis.jpa.internal.query.QueryBuilder Maven / Gradle / Ivy
package io.katharsis.jpa.internal.query;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.katharsis.jpa.internal.meta.MetaAttribute;
import io.katharsis.jpa.internal.meta.MetaAttributeFinder;
import io.katharsis.jpa.internal.meta.MetaAttributePath;
import io.katharsis.jpa.internal.meta.MetaDataObject;
import io.katharsis.jpa.internal.meta.MetaEntity;
import io.katharsis.jpa.internal.meta.MetaKey;
import io.katharsis.jpa.internal.query.backend.JpaQueryBackend;
import io.katharsis.queryspec.FilterSpec;
import io.katharsis.queryspec.IncludeFieldSpec;
public class QueryBuilder {
private static final String SORT_COLUMN_ALIAS_PREFIX = "__sort";
private JpaQueryBackend backend;
private AbstractJpaQueryImpl query;
private MetaAttributeFinder attributeFinder;
public QueryBuilder(AbstractJpaQueryImpl query, JpaQueryBackend backend) {
this.query = query;
this.backend = backend;
final ComputedAttributeRegistryImpl virtualAttrs = query.getComputedAttrs();
this.attributeFinder = new MetaAttributeFinder() {
@Override
public MetaAttribute getAttribute(MetaDataObject meta, String name) {
MetaComputedAttribute attr = virtualAttrs.get(meta, name);
if (attr != null) {
return attr;
}
return meta.findAttribute(name, true);
}
};
}
/**
* Adds order expressions to selection if in "auto distinct" mode and
* the query performs a join or fetch on a relation. In
* this case, attributes from referenced entities inlucded in the sort
* clause must be added to the select clause as well.
*
* @return number of attributes that were needed to compute a distinct
*/
protected int applyDistinct() {
int numAutoSelections = 0;
boolean distinct;
if (query.autoDistinct) {
// distinct for many join/fetches or manual
// in case of ViewQuery we may not need this here, but we need to do
// the selection of order-by columns below
distinct = query.autoDistinct && !query.autoGroupBy && backend.hasManyRootsFetchesOrJoins();
if (distinct) {
// we also need to select sorted attributes (for references)
numAutoSelections = addOrderExpressionsToSelection();
}
}
else {
distinct = query.distinct;
}
if (distinct) {
backend.distinct();
}
return numAutoSelections;
}
public Map applySelectionSpec() {
MetaDataObject meta = query.getMeta();
Map selectionBindings = new HashMap<>();
int index = 1;
List includedFields = query.getIncludedFields();
for (IncludeFieldSpec includedField : includedFields) {
MetaAttributePath path = meta.resolvePath(includedField.getAttributePath(), attributeFinder);
E attr = backend.getAttribute(path);
backend.addSelection(attr, path.toString());
selectionBindings.put(path.toString(), index++);
}
return selectionBindings;
}
private int addOrderExpressionsToSelection() {
int numAutoSelections = 0;
int prefixIndex = 0;
List newOrderList = new ArrayList<>();
for (O order : backend.getOrderList()) {
E expression = backend.getExpression(order);
if (backend.containsRelation(expression)) {
backend.addSelection(expression, SORT_COLUMN_ALIAS_PREFIX + prefixIndex++);
numAutoSelections++;
}
newOrderList.add(order);
}
backend.setOrder(newOrderList);
return numAutoSelections;
}
protected void applySortSpec() {
QuerySortBuilder orderBuilder = new QuerySortBuilder<>(query, backend);
orderBuilder.applySortSpec();
}
protected void applyFilterSpec() {
QueryFilterBuilder predicateBuilder = new QueryFilterBuilder<>(query.getComputedAttrs(), backend, attributeFinder);
MetaDataObject meta = query.getMeta();
List filters = query.getFilterSpecs();
List predicates = predicateBuilder.filterSpecListToPredicateArray(meta, backend.getRoot(), filters);
if (predicates != null && !predicates.isEmpty()) {
backend.addPredicate(backend.and(predicates));
}
MetaAttribute parentAttr = query.getParentAttr();
if (parentAttr != null) {
MetaEntity parentEntity = parentAttr.getParent().asEntity();
MetaKey primaryKey = parentEntity.getPrimaryKey();
MetaAttribute primaryKeyAttr = primaryKey.getUniqueElement();
backend.addParentPredicate(primaryKeyAttr);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy