Skip to content

Commit

Permalink
[Blazebit#305] Make use of a different entity function node rendering…
Browse files Browse the repository at this point in the history
… technique to prevent parameter order confusion. Fixes Blazebit#305
  • Loading branch information
beikov committed Jul 22, 2018
1 parent f6fc9a4 commit 23a6756
Show file tree
Hide file tree
Showing 41 changed files with 923 additions and 535 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ None

### Bug fixes

None
* Problems with the use of the `VALUES` clause and parameters in the select clause have been fixed

### Backwards-incompatible changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,22 @@ public interface ExtendedQuerySupport {
*
* @param serviceProvider The service provider to access {@linkplain EntityManager} and others
* @param participatingQueries The list of participating queries from which to combine parameters
* @param baseQuery The base query which represents the original modification query
* @param query The main query to execute
* @param sqlOverride The actual SQL query to execute instead of the query's original SQL
* @return The update count of the query
*/
public int executeUpdate(ServiceProvider serviceProvider, List<Query> participatingQueries, Query query, String sqlOverride);
public int executeUpdate(ServiceProvider serviceProvider, List<Query> participatingQueries, Query baseQuery, Query query, String sqlOverride);

/**
* Executes and returns the returning result of the Query by replacing the SQL with the given overriding SQL query.
*
* @param serviceProvider The service provider to access {@linkplain EntityManager} and others
* @param participatingQueries The list of participating queries from which to combine parameters
* @param baseQuery The base query which represents the original modification query
* @param exampleQuery The example query providing the result type structure
* @param sqlOverride The actual SQL query to execute instead of the query's original SQL
* @return The returning result of the query
*/
public ReturningResult<Object[]> executeReturning(ServiceProvider serviceProvider, List<Query> participatingQueries, Query exampleQuery, String sqlOverride);
public ReturningResult<Object[]> executeReturning(ServiceProvider serviceProvider, List<Query> participatingQueries, Query baseQuery, Query exampleQuery, String sqlOverride);
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external
sbSelectFrom.append(entityType.getName());
sbSelectFrom.append('(').append(collectionName).append(") ");
sbSelectFrom.append(entityAlias);
appendWhereClause(sbSelectFrom);
appendWhereClause(sbSelectFrom, externalRepresentation);
} else {
// The internal representation is just a "hull" to hold the parameters at the appropriate positions
sbSelectFrom.append("SELECT 1 FROM ");
Expand All @@ -76,7 +76,7 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external
sbSelectFrom.append(" LEFT JOIN ");
sbSelectFrom.append(entityAlias).append('.').append(collectionName)
.append(' ').append(CollectionDeleteModificationQuerySpecification.COLLECTION_BASE_QUERY_ALIAS);
appendWhereClause(sbSelectFrom);
appendWhereClause(sbSelectFrom, externalRepresentation);
}
}

Expand Down Expand Up @@ -120,7 +120,7 @@ private <R> QuerySpecification getQuerySpecification(Query baseQuery, Query exam

boolean isEmbedded = this instanceof ReturningBuilder;
boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(baseQuery, isEmbedded) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;

// Prepare a Map<EntityAlias.idColumnName, CollectionAlias.idColumnName>
// This is used to replace references to id columns properly in the final sql query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ private String buildPageCountQueryString(StringBuilder sbSelectFrom, boolean ext
// The count query does not have any fetch owners
Set<JoinNode> countNodesToFetch = Collections.emptySet();
// Collect usage of collection join nodes to optimize away the count distinct
Set<JoinNode> collectionJoinNodes = joinManager.buildClause(sbSelectFrom, EnumSet.of(ClauseType.ORDER_BY, ClauseType.SELECT), null, true, externalRepresentation, whereClauseConjuncts, explicitVersionEntities, countNodesToFetch);
Set<JoinNode> collectionJoinNodes = joinManager.buildClause(sbSelectFrom, EnumSet.of(ClauseType.ORDER_BY, ClauseType.SELECT), null, true, externalRepresentation, whereClauseConjuncts, null, explicitVersionEntities, countNodesToFetch);
// TODO: Maybe we can improve this and treat array access joins like non-collection join nodes
boolean hasCollectionJoinUsages = collectionJoinNodes.size() > 0;

whereManager.buildClause(sbSelectFrom, whereClauseConjuncts);
whereManager.buildClause(sbSelectFrom, whereClauseConjuncts, null);

// Count distinct is obviously unnecessary if we have no collection joins
if (!hasCollectionJoinUsages) {
Expand Down Expand Up @@ -189,7 +189,7 @@ public TypedQuery<Long> getCountQuery() {
List<String> keyRestrictedLeftJoinAliases = getKeyRestrictedLeftJoinAliases(baseQuery, keyRestrictedLeftJoins, EnumSet.of(ClauseType.ORDER_BY, ClauseType.SELECT));
List<EntityFunctionNode> entityFunctionNodes = getEntityFunctionNodes(baseQuery);
boolean shouldRenderCteNodes = renderCteNodes(false);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(baseQuery, false) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(false) : Collections.EMPTY_LIST;
QuerySpecification querySpecification = new CustomQuerySpecification(
this, baseQuery, parameterManager.getParameters(), parameterListNames, null, null, keyRestrictedLeftJoinAliases, entityFunctionNodes, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ private <R> QuerySpecification getQuerySpecification(Query baseQuery, Query exam

boolean isEmbedded = this instanceof ReturningBuilder;
boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(baseQuery, isEmbedded) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;

ExtendedQuerySupport extendedQuerySupport = getService(ExtendedQuerySupport.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ protected Query getQuery(Map<DbmsModificationState, String> includedModification
boolean isEmbedded = this instanceof ReturningBuilder;
String[] returningColumns = getReturningColumns();
boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(query, isEmbedded) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;

QuerySpecification querySpecification = new ModificationQuerySpecification(
this,
Expand Down Expand Up @@ -345,7 +345,7 @@ public <Z> TypedQuery<ReturningResult<Z>> getWithReturningQuery(ReturningObjectB
protected <R> TypedQuery<ReturningResult<R>> getExecuteWithReturningQuery(TypedQuery<Object[]> exampleQuery, Query baseQuery, String[] returningColumns, ReturningObjectBuilder<R> objectBuilder) {
Set<String> parameterListNames = parameterManager.getParameterListNames(baseQuery);
boolean shouldRenderCteNodes = renderCteNodes(false);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(baseQuery, false) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(false) : Collections.EMPTY_LIST;
QuerySpecification querySpecification = new ReturningModificationQuerySpecification<R>(
this, baseQuery, exampleQuery, parameterManager.getParameters(), parameterListNames, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, returningColumns, objectBuilder
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external
sbSelectFrom.append('(').append(collectionName).append(") ");
sbSelectFrom.append(entityAlias);
appendSetClause(sbSelectFrom);
appendWhereClause(sbSelectFrom);
appendWhereClause(sbSelectFrom, externalRepresentation);
} else {
// The internal representation is just a "hull" to hold the parameters at the appropriate positions
sbSelectFrom.append("SELECT 1 FROM ");
Expand All @@ -120,7 +120,7 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external
sbSelectFrom.append(" LEFT JOIN ");
sbSelectFrom.append(entityAlias).append('.').append(collectionName)
.append(' ').append(CollectionUpdateModificationQuerySpecification.COLLECTION_BASE_QUERY_ALIAS);
appendWhereClause(sbSelectFrom);
appendWhereClause(sbSelectFrom, externalRepresentation);

// Create the select query strings that are used for the set items
// The idea is to encode a set item as an equality predicate in a dedicated query
Expand Down Expand Up @@ -205,7 +205,7 @@ private <R> QuerySpecification getQuerySpecification(Query baseQuery, Query exam

boolean isEmbedded = this instanceof ReturningBuilder;
boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(baseQuery, isEmbedded) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;

ExtendedQuerySupport extendedQuerySupport = getService(ExtendedQuerySupport.class);
String sql = extendedQuerySupport.getSql(em, baseQuery);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external
sbSelectFrom.append("DELETE FROM ");
sbSelectFrom.append(entityType.getName()).append(' ');
sbSelectFrom.append(entityAlias);
appendWhereClause(sbSelectFrom);
appendWhereClause(sbSelectFrom, externalRepresentation);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ protected TypedQuery<T> getTypedQuery() {
List<String> keyRestrictedLeftJoinAliases = Collections.emptyList();
List<EntityFunctionNode> entityFunctionNodes = getEntityFunctionNodes(baseQuery);
boolean shouldRenderCteNodes = renderCteNodes(false);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(baseQuery, false) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(false) : Collections.EMPTY_LIST;
QuerySpecification querySpecification = new SetOperationQuerySpecification(
this,
leftMostQuery,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ protected Query getQuery(Map<DbmsModificationState, String> includedModification
boolean isEmbedded = this instanceof ReturningBuilder;
String[] returningColumns = getReturningColumns();
boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(query, isEmbedded) : Collections.EMPTY_LIST;
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;

QuerySpecification querySpecification = new ModificationQuerySpecification(
this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ protected void buildBaseQueryString(StringBuilder sbSelectFrom, boolean external
sbSelectFrom.append(entityType.getName()).append(' ');
sbSelectFrom.append(entityAlias);
appendSetClause(sbSelectFrom);
appendWhereClause(sbSelectFrom);
appendWhereClause(sbSelectFrom, externalRepresentation);
}

protected void appendSetClause(StringBuilder sbSelectFrom) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.blazebit.persistence.impl.dialect.MySQLDbmsDialect;
import com.blazebit.persistence.impl.dialect.OracleDbmsDialect;
import com.blazebit.persistence.impl.dialect.PostgreSQLDbmsDialect;
import com.blazebit.persistence.impl.function.entity.EntityFunction;
import com.blazebit.persistence.impl.function.subquery.SubqueryFunction;
import com.blazebit.persistence.parser.expression.ConcurrentHashMapExpressionCache;
import com.blazebit.persistence.impl.function.cast.CastFunction;
Expand Down Expand Up @@ -220,6 +221,12 @@ private void loadFunctions() {
jpqlFunctionGroup.add("sybase", new TransactSQLPagePositionFunction());
jpqlFunctionGroup.add("microsoft", new TransactSQLPagePositionFunction());
registerFunction(jpqlFunctionGroup);

// entity_function

jpqlFunctionGroup = new JpqlFunctionGroup(EntityFunction.FUNCTION_NAME, false);
jpqlFunctionGroup.add(null, new EntityFunction());
registerFunction(jpqlFunctionGroup);

// set operations

Expand Down
Loading

0 comments on commit 23a6756

Please sign in to comment.