Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.blazebit.persistence.impl.CTEManager Maven / Gradle / Ivy
/*
* Copyright 2014 - 2020 Blazebit.
*
* 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 com.blazebit.persistence.impl;
import com.blazebit.persistence.FullSelectCTECriteriaBuilder;
import com.blazebit.persistence.LeafOngoingFinalSetOperationCTECriteriaBuilder;
import com.blazebit.persistence.ReturningModificationCriteriaBuilderFactory;
import com.blazebit.persistence.SelectRecursiveCTECriteriaBuilder;
import com.blazebit.persistence.StartOngoingSetOperationCTECriteriaBuilder;
import com.blazebit.persistence.parser.expression.ExpressionCopyContext;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author Christian Beikov
* @author Moritz Becker
* @since 1.1.0
*/
public class CTEManager extends CTEBuilderListenerImpl {
private final MainQuery mainQuery;
private final Map ctes;
private QueryContext queryContext;
private boolean recursive = false;
CTEManager(MainQuery mainQuery) {
this.mainQuery = mainQuery;
this.ctes = new LinkedHashMap<>();
}
void init(AbstractCommonQueryBuilder queryBuilder) {
if (queryContext == null) {
this.queryContext = new QueryContext(queryBuilder, ClauseType.CTE);
}
}
void applyFrom(CTEManager cteManager, Map joinManagerMapping, ExpressionCopyContext copyContext) {
if (cteManager.recursive) {
recursive = true;
}
for (Map.Entry entry : cteManager.ctes.entrySet()) {
CTEInfo cteInfo = entry.getValue().copy(this, joinManagerMapping, copyContext);
mainQuery.parameterManager.collectParameterRegistrations(cteInfo.nonRecursiveCriteriaBuilder, ClauseType.CTE);
if (cteInfo.recursive) {
mainQuery.parameterManager.collectParameterRegistrations(cteInfo.recursiveCriteriaBuilder, ClauseType.CTE);
}
ctes.put(entry.getKey(), cteInfo);
}
}
QueryContext getQueryContext() {
return queryContext;
}
Collection getCtes() {
return ctes.values();
}
public boolean hasCte(Class cte) {
return ctes.containsKey(getCteKey(cte, null, null));
}
public CTEInfo getCte(Class cteType) {
return ctes.get(getCteKey(cteType, null, null));
}
public CTEInfo getCte(Class cteType, String name, JoinManager joinManager) {
return ctes.get(getCteKey(cteType, name, joinManager));
}
private CTEKey getCteKey(Class cteClass, String name, JoinManager owner) {
return new CTEKey(cteClass, name, owner);
}
private void assertCteNameAvailable(CTEKey cteKey) {
if (ctes.containsKey(cteKey)) {
throw new IllegalArgumentException("A CTE with the name " + cteKey.getName() + " already exists! Please choose a different type or name!");
}
}
public boolean hasCtes() {
if (ctes.size() > 0) {
for (CTEInfo cteInfo : ctes.values()) {
if (!cteInfo.inline) {
return true;
}
}
}
return false;
}
boolean isRecursive() {
return recursive;
}
void buildClause(StringBuilder sb) {
if (ctes.isEmpty()) {
return;
}
int startLength = sb.length();
sb.append("WITH ");
if (recursive) {
sb.append("RECURSIVE ");
}
boolean first = true;
for (CTEInfo cte : ctes.values()) {
if (!cte.inline) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(cte.name);
sb.append('(');
final List attributes = cte.attributes;
sb.append(attributes.get(0));
for (int i = 1; i < attributes.size(); i++) {
sb.append(", ");
sb.append(attributes.get(i));
}
sb.append(')');
sb.append(" AS(\n");
sb.append(cte.nonRecursiveCriteriaBuilder.getQueryString());
if (cte.recursive) {
sb.append(cte.unionAll ? "\nUNION ALL\n" : "\nUNION\n");
sb.append(cte.recursiveCriteriaBuilder.getQueryString());
}
sb.append("\n)");
}
}
if (first) {
sb.setLength(startLength);
} else {
sb.append("\n");
}
}
@SuppressWarnings("unchecked")
StartOngoingSetOperationCTECriteriaBuilder> withStartSet(Class cteClass, Y result, boolean inline, AliasManager parentAliasManager, JoinManager parentJoinManager) {
mainQuery.assertSupportsAdvancedSql("Illegal use of WITH clause!", inline);
CTEKey cteKey = getCteKey(cteClass, null, null);
FinalSetOperationCTECriteriaBuilderImpl parentFinalSetOperationBuilder = new FinalSetOperationCTECriteriaBuilderImpl(mainQuery, queryContext, (Class) cteClass, result, null, false, this, null);
OngoingFinalSetOperationCTECriteriaBuilderImpl subFinalSetOperationBuilder = new OngoingFinalSetOperationCTECriteriaBuilderImpl(mainQuery, queryContext, (Class) cteClass, null, null, true, parentFinalSetOperationBuilder.getSubListener(), null);
this.onBuilderStarted(parentFinalSetOperationBuilder);
LeafOngoingSetOperationCTECriteriaBuilderImpl leafCb = new LeafOngoingSetOperationCTECriteriaBuilderImpl(mainQuery, queryContext, cteKey, inline, (Class) cteClass, result, parentFinalSetOperationBuilder.getSubListener(), (FinalSetOperationCTECriteriaBuilderImpl) parentFinalSetOperationBuilder, parentAliasManager, parentJoinManager);
StartOngoingSetOperationCTECriteriaBuilderImpl> cb = new StartOngoingSetOperationCTECriteriaBuilderImpl>(
mainQuery, queryContext, cteKey, inline, (Class) cteClass, result, subFinalSetOperationBuilder.getSubListener(), (OngoingFinalSetOperationCTECriteriaBuilderImpl) subFinalSetOperationBuilder, leafCb, parentAliasManager, parentJoinManager
);
subFinalSetOperationBuilder.setOperationManager.setStartQueryBuilder(cb);
parentFinalSetOperationBuilder.setOperationManager.setStartQueryBuilder(subFinalSetOperationBuilder);
subFinalSetOperationBuilder.getSubListener().onBuilderStarted(cb);
parentFinalSetOperationBuilder.getSubListener().onBuilderStarted(leafCb);
// Generics hell..
return (StartOngoingSetOperationCTECriteriaBuilder) cb;
}
@SuppressWarnings("unchecked")
FullSelectCTECriteriaBuilder with(Class cteClass, String name, Y result, boolean inline, JoinManager inlineOwner, AliasManager parentAliasManager, JoinManager parentJoinManager) {
mainQuery.assertSupportsAdvancedSql("Illegal use of WITH clause!", inline);
CTEKey cteKey = getCteKey(cteClass, name, inlineOwner);
assertCteNameAvailable(cteKey);
FullSelectCTECriteriaBuilderImpl cteBuilder = new FullSelectCTECriteriaBuilderImpl(mainQuery, queryContext, cteKey, inline, (Class) cteClass, result, this, parentAliasManager, parentJoinManager);
this.onBuilderStarted(cteBuilder);
return cteBuilder;
}
@SuppressWarnings("unchecked")
FullSelectCTECriteriaBuilder with(Class cteClass, Y result, AbstractCommonQueryBuilder builder, boolean inline, JoinManager inlineOwner, AliasManager parentAliasManager, JoinManager parentJoinManager) {
mainQuery.assertSupportsAdvancedSql("Illegal use of WITH clause!", inline);
CTEKey cteKey = getCteKey(cteClass, null, inlineOwner);
assertCteNameAvailable(cteKey);
FullSelectCTECriteriaBuilderImpl cteBuilder = new FullSelectCTECriteriaBuilderImpl(mainQuery, queryContext, cteKey, inline, (Class) cteClass, result, this, parentAliasManager, parentJoinManager);
cteBuilder.applyFrom(builder, true, false, false, Collections.emptySet(), Collections.emptySet(), new IdentityHashMap(), ExpressionCopyContext.EMPTY);
this.onBuilderStarted(cteBuilder);
return cteBuilder;
}
@SuppressWarnings("unchecked")
SelectRecursiveCTECriteriaBuilder withRecursive(Class cteClass, Y result) {
mainQuery.assertSupportsAdvancedSql("Illegal use of WITH clause!");
CTEKey cteKey = getCteKey(cteClass, null, null);
assertCteNameAvailable(cteKey);
recursive = true;
RecursiveCTECriteriaBuilderImpl cteBuilder = new RecursiveCTECriteriaBuilderImpl(mainQuery, queryContext, cteKey, (Class) cteClass, result, this);
this.onBuilderStarted(cteBuilder);
return cteBuilder;
}
ReturningModificationCriteriaBuilderFactory withReturning(Class cteClass, Y result) {
mainQuery.assertSupportsAdvancedSql("Illegal use of WITH clause!");
CTEKey cteKey = getCteKey(cteClass, null, null);
assertCteNameAvailable(cteKey);
ReturningModificationCriteraBuilderFactoryImpl factory = new ReturningModificationCriteraBuilderFactoryImpl(mainQuery, cteKey, cteClass, result, this);
return factory;
}
@Override
public void onBuilderEnded(CTEInfoBuilder builder) {
super.onBuilderEnded(builder);
CTEInfo cteInfo = builder.createCTEInfo();
mainQuery.parameterManager.collectParameterRegistrations(cteInfo.nonRecursiveCriteriaBuilder, ClauseType.CTE);
if (cteInfo.recursive) {
mainQuery.parameterManager.collectParameterRegistrations(cteInfo.recursiveCriteriaBuilder, ClauseType.CTE);
}
ctes.put(new CTEKey(cteInfo.name, cteInfo.owner), cteInfo);
}
/**
* @author Christian Beikov
* @since 1.4.1
*/
static final class CTEKey {
private final String name;
private final JoinManager owner;
public CTEKey(Class cteType, String name, JoinManager owner) {
if (name == null) {
this.name = cteType.getSimpleName();
} else {
this.name = cteType.getSimpleName() + "." + name;
}
this.owner = owner;
}
public CTEKey(String name, JoinManager owner) {
this.name = name;
this.owner = owner;
}
public String getName() {
return name;
}
public JoinManager getOwner() {
return owner;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof CTEKey)) {
return false;
}
CTEKey cteKey = (CTEKey) o;
if (name != null ? !name.equals(cteKey.name) : cteKey.name != null) {
return false;
}
return owner != null ? owner.equals(cteKey.owner) : cteKey.owner == null;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + (owner != null ? owner.hashCode() : 0);
return result;
}
}
}