/** * Make a new FilterParsingResult after normalizing the query. This FilterParsingResult is not supposed to have * grouping/aggregation. */ private IckleParsingResult<TypeMetadata> makeFilterParsingResult(IckleParsingResult<TypeMetadata> parsingResult, BooleanExpr normalizedWhereClause, PropertyPath[] projection, Class<?>[] projectedTypes, Object[] projectedNullMarkers, SortField[] sortFields) { String queryString = SyntaxTreePrinter.printTree(parsingResult.getTargetEntityName(), projection, normalizedWhereClause, sortFields); return new IckleParsingResult<>(queryString, parsingResult.getParameterNames(), normalizedWhereClause, null, parsingResult.getTargetEntityName(), parsingResult.getTargetEntityMetadata(), projection, projectedTypes, projectedNullMarkers, null, sortFields); }
@Override public String[] getProjection() { return parsingResult.getProjections(); }
protected BaseQuery buildQuery(QueryFactory queryFactory, IckleParsingResult<TypeMetadata> parsingResult, Map<String, Object> namedParameters, long startOffset, int maxResults) { if (log.isDebugEnabled()) { log.debugf("Building query '%s' with parameters %s", parsingResult.getQueryString(), namedParameters); } BaseQuery query = parsingResult.hasGroupingOrAggregations() ? buildQueryWithAggregations(queryFactory, parsingResult.getQueryString(), namedParameters, startOffset, maxResults, parsingResult) : buildQueryNoAggregations(queryFactory, parsingResult.getQueryString(), namedParameters, startOffset, maxResults, parsingResult); query.validateNamedParameters(); return query; }
private BaseQuery buildQueryNoAggregations(QueryFactory queryFactory, String queryString, Map<String, Object> namedParameters, long startOffset, int maxResults, IckleParsingResult<TypeMetadata> parsingResult) { if (parsingResult.hasGroupingOrAggregations()) { throw log.queryMustNotUseGroupingOrAggregation(); // may happen only due to internal programming error if (parsingResult.getWhereClause() != null) { isFullTextQuery = parsingResult.getWhereClause().acceptVisitor(FullTextVisitor.INSTANCE); if (!isIndexed && isFullTextQuery) { throw new IllegalStateException("The cache must be indexed in order to use full-text queries."); if (parsingResult.getSortFields() != null) { for (SortField sortField : parsingResult.getSortFields()) { PropertyPath<?> p = sortField.getPath(); if (propertyHelper.isRepeatedProperty(parsingResult.getTargetEntityMetadata(), p.asArrayPath())) { throw log.multivaluedPropertyCannotBeUsedInOrderBy(p.toString()); if (parsingResult.getProjectedPaths() != null) { for (PropertyPath<?> p : parsingResult.getProjectedPaths()) { if (propertyHelper.isRepeatedProperty(parsingResult.getTargetEntityMetadata(), p.asArrayPath())) { throw log.multivaluedPropertyCannotBeProjected(p.asStringPath()); BooleanExpr normalizedWhereClause = booleanFilterNormalizer.normalize(parsingResult.getWhereClause()); if (normalizedWhereClause == ConstantBooleanExpr.FALSE) { return new EmbeddedQuery(this, queryFactory, cache, queryString, namedParameters, parsingResult.getProjections(), startOffset, maxResults); IndexedFieldProvider.FieldIndexingMetadata fieldIndexingMetadata = propertyHelper.getIndexedFieldProvider().get(parsingResult.getTargetEntityMetadata()); if (parsingResult.getProjectedPaths() != null) { projectionsMap = new LinkedHashMap<>();
private BaseQuery buildQueryWithAggregations(QueryFactory queryFactory, String queryString, Map<String, Object> namedParameters, long startOffset, int maxResults, IckleParsingResult<TypeMetadata> parsingResult) { if (parsingResult.getProjectedPaths() == null) { throw log.groupingAndAggregationQueriesMustUseProjections(); if (parsingResult.getGroupBy() != null) { for (PropertyPath<?> p : parsingResult.getGroupBy()) { if (p instanceof AggregationPropertyPath) { throw log.cannotHaveAggregationsInGroupByClause(); // should not really be possible because this was validated during parsing if (propertyHelper.isRepeatedProperty(parsingResult.getTargetEntityMetadata(), p.asArrayPath())) { Class<?> propertyType = propertyHelper.getPrimitivePropertyType(parsingResult.getTargetEntityMetadata(), p.asArrayPath()); int idx = columns.size(); columns.put(p, new RowPropertyHelper.ColumnMetadata(idx, "C" + idx, propertyType)); for (int i = 0; i < parsingResult.getProjectedPaths().length; i++) { PropertyPath<?> p = parsingResult.getProjectedPaths()[i]; RowPropertyHelper.ColumnMetadata c = columns.get(p); if (!(p instanceof AggregationPropertyPath)) { Class<?> propertyType = FieldAccumulator.getOutputType(((AggregationPropertyPath) p).getAggregationFunction(), parsingResult.getProjectedTypes()[i]); int idx = columns.size(); columns.put(p, new RowPropertyHelper.ColumnMetadata(idx, "C" + idx, propertyType)); if (parsingResult.getSortFields() != null) { for (SortField sortField : parsingResult.getSortFields()) { PropertyPath<?> p = sortField.getPath(); RowPropertyHelper.ColumnMetadata c = columns.get(p); Class<?> propertyType = propertyHelper.getPrimitivePropertyType(parsingResult.getTargetEntityMetadata(), p.asArrayPath());
@Override public ObjectFilter getObjectFilter(String queryString, List<FieldAccumulator> acc) { final IckleParsingResult<TypeMetadata> parsingResult = IckleParser.parse(queryString, propertyHelper); disallowGroupingAndAggregations(parsingResult); // if the query is a contradiction just return an ObjectFilter that rejects everything if (parsingResult.getWhereClause() == ConstantBooleanExpr.FALSE) { return new RejectObjectFilter<>(null, parsingResult); } final MetadataAdapter<TypeMetadata, AttributeMetadata, AttributeId> metadataAdapter = createMetadataAdapter(parsingResult.getTargetEntityMetadata()); // if the query is a tautology or there is no query at all and there is no sorting or projections just return a special instance that accepts anything // in case we have sorting and projections we cannot take this shortcut because the computation of projections or sort projections is a bit more involved if ((parsingResult.getWhereClause() == null || parsingResult.getWhereClause() == ConstantBooleanExpr.TRUE) && parsingResult.getSortFields() == null && parsingResult.getProjectedPaths() == null) { return new AcceptObjectFilter<>(null, this, metadataAdapter, parsingResult); } FieldAccumulator[] accumulators = acc != null ? acc.toArray(new FieldAccumulator[acc.size()]) : null; return new ObjectFilterImpl<>(this, metadataAdapter, parsingResult, accumulators); }
@Override public FilterSubscription registerFilter(String queryString, Map<String, Object> namedParameters, FilterCallback callback, boolean isDeltaFilter, Object... eventType) { IckleParsingResult<TypeMetadata> parsingResult = IckleParser.parse(queryString, propertyHelper); disallowGroupingAndAggregations(parsingResult); disallowFullText(parsingResult); Map<TypeMetadata, FilterRegistry<TypeMetadata, AttributeMetadata, AttributeId>> filterMap = isDeltaFilter ? deltaFiltersByType : filtersByType; write.lock(); try { FilterRegistry<TypeMetadata, AttributeMetadata, AttributeId> filterRegistry = filterMap.get(parsingResult.getTargetEntityMetadata()); if (filterRegistry == null) { filterRegistry = new FilterRegistry<>(createMetadataAdapter(parsingResult.getTargetEntityMetadata()), true); filterMap.put(filterRegistry.getMetadataAdapter().getTypeMetadata(), filterRegistry); } return filterRegistry.addFilter(queryString, namedParameters, parsingResult.getWhereClause(), parsingResult.getProjections(), parsingResult.getProjectedTypes(), parsingResult.getSortFields(), callback, isDeltaFilter, eventType); } finally { write.unlock(); } }
public LuceneQueryParsingResult<TypeMetadata> transform(IckleParsingResult<TypeMetadata> parsingResult, Map<String, Object> namedParameters, Class<?> targetedType) { this.namedParameters = namedParameters; EntityContext entityContext = queryContextBuilder.forEntity(targetedType); fieldBridgeAndAnalyzerProvider.overrideAnalyzers(parsingResult, entityContext); queryBuilder = entityContext.get(); entityType = parsingResult.getTargetEntityMetadata(); AnalyzerReference analyzerReference = ((ExtendedSearchIntegrator) searchFactory).getAnalyzerReference(new PojoIndexedTypeIdentifier(targetedType)); if (analyzerReference.is(LuceneAnalyzerReference.class)) { entityAnalyzer = analyzerReference.unwrap(LuceneAnalyzerReference.class).getAnalyzer(); } Query query = makeQuery(parsingResult.getWhereClause()); // an all negative top level boolean query is not allowed; needs a bit of rewriting if (query instanceof BooleanQuery) { BooleanQuery booleanQuery = (BooleanQuery) query; boolean allClausesAreMustNot = booleanQuery.clauses().stream().allMatch(c -> c.getOccur() == BooleanClause.Occur.MUST_NOT); if (allClausesAreMustNot) { //It is illegal to have only must-not queries, in this case we need to add a positive clause to match everything else. BooleanQuery.Builder builder = new BooleanQuery.Builder(); for (BooleanClause clause : booleanQuery.clauses()) { builder.add(clause.getQuery(), BooleanClause.Occur.MUST_NOT); } builder.add(new MatchAllDocsQuery(), BooleanClause.Occur.FILTER); query = builder.build(); } } Sort sort = makeSort(parsingResult.getSortFields()); return new LuceneQueryParsingResult<>(query, parsingResult.getTargetEntityName(), parsingResult.getTargetEntityMetadata(), parsingResult.getProjections(), sort); }
private LuceneQueryParsingResult<TypeMetadata> transformParsingResult(IckleParsingResult<TypeMetadata> parsingResult, Map<String, Object> namedParameters) { return queryCache != null && parsingResult.getParameterNames().isEmpty() ? queryCache.get(parsingResult.getQueryString(), null, LuceneQueryParsingResult.class, (queryString, accumulators) -> transformToLuceneQueryParsingResult(parsingResult, namedParameters)) : transformToLuceneQueryParsingResult(parsingResult, namedParameters); }
protected Class<?> getTargetedClass(IckleParsingResult<?> parsingResult) { return (Class<?>) parsingResult.getTargetEntityMetadata(); }
EmbeddedLuceneQuery(QueryEngine<TypeMetadata> queryEngine, QueryFactory queryFactory, Map<String, Object> namedParameters, IckleParsingResult<TypeMetadata> parsingResult, String[] projection, ResultProcessor resultProcessor, long startOffset, int maxResults) { super(queryFactory, parsingResult.getQueryString(), namedParameters, projection, startOffset, maxResults); if (resultProcessor instanceof RowProcessor && (projection == null || projection.length == 0)) { throw new IllegalArgumentException("A RowProcessor can only be specified with projections"); } this.queryEngine = queryEngine; this.resultProcessor = resultProcessor; this.parsingResult = parsingResult; }
@Override public Set<String> getParameterNames() { return parsingResult.getParameterNames(); }
public IckleParsingResult<TypeMetadata> getResult() { return new IckleParsingResult<>( queryString, Collections.unmodifiableSet(new HashSet<>(namedParameters.keySet())), whereBuilder.build(), havingBuilder.build(), targetTypeName, targetEntityMetadata, projections == null ? null : projections.toArray(new PropertyPath[projections.size()]), projectedTypes == null ? null : projectedTypes.toArray(new Class<?>[projectedTypes.size()]), projectedNullMarkers == null ? null : projectedNullMarkers.toArray(new Object[projectedNullMarkers.size()]), groupBy == null ? null : groupBy.toArray(new PropertyPath[groupBy.size()]), sortFields == null ? null : sortFields.toArray(new SortField[sortFields.size()])); } }
private BaseQuery buildQueryNoAggregations(QueryFactory queryFactory, String queryString, Map<String, Object> namedParameters, long startOffset, int maxResults, IckleParsingResult<TypeMetadata> parsingResult, IndexedQueryMode queryMode) { if (parsingResult.hasGroupingOrAggregations()) { throw log.queryMustNotUseGroupingOrAggregation(); // may happen only due to internal programming error if (parsingResult.getWhereClause() != null) { isFullTextQuery = parsingResult.getWhereClause().acceptVisitor(FullTextVisitor.INSTANCE); if (!isIndexed && isFullTextQuery) { throw new IllegalStateException("The cache must be indexed in order to use full-text queries."); if (parsingResult.getSortFields() != null) { for (SortField sortField : parsingResult.getSortFields()) { PropertyPath<?> p = sortField.getPath(); if (propertyHelper.isRepeatedProperty(parsingResult.getTargetEntityMetadata(), p.asArrayPath())) { throw log.multivaluedPropertyCannotBeUsedInOrderBy(p.toString()); if (parsingResult.getProjectedPaths() != null) { for (PropertyPath<?> p : parsingResult.getProjectedPaths()) { if (propertyHelper.isRepeatedProperty(parsingResult.getTargetEntityMetadata(), p.asArrayPath())) { throw log.multivaluedPropertyCannotBeProjected(p.asStringPath()); BooleanExpr normalizedWhereClause = booleanFilterNormalizer.normalize(parsingResult.getWhereClause()); if (normalizedWhereClause == ConstantBooleanExpr.FALSE) { return new EmbeddedQuery(this, queryFactory, cache, queryString, namedParameters, parsingResult.getProjections(), startOffset, maxResults); IndexedFieldProvider.FieldIndexingMetadata fieldIndexingMetadata = propertyHelper.getIndexedFieldProvider().get(parsingResult.getTargetEntityMetadata()); if (parsingResult.getProjectedPaths() != null) { projectionsMap = new LinkedHashMap<>();
private BaseQuery buildQueryWithAggregations(QueryFactory queryFactory, String queryString, Map<String, Object> namedParameters, long startOffset, int maxResults, IckleParsingResult<TypeMetadata> parsingResult, IndexedQueryMode queryMode) { if (parsingResult.getProjectedPaths() == null) { throw log.groupingAndAggregationQueriesMustUseProjections(); if (parsingResult.getGroupBy() != null) { for (PropertyPath<?> p : parsingResult.getGroupBy()) { if (p instanceof AggregationPropertyPath) { throw log.cannotHaveAggregationsInGroupByClause(); // should not really be possible because this was validated during parsing if (propertyHelper.isRepeatedProperty(parsingResult.getTargetEntityMetadata(), p.asArrayPath())) { Class<?> propertyType = propertyHelper.getPrimitivePropertyType(parsingResult.getTargetEntityMetadata(), p.asArrayPath()); int idx = columns.size(); columns.put(p, new RowPropertyHelper.ColumnMetadata(idx, "C" + idx, propertyType)); for (int i = 0; i < parsingResult.getProjectedPaths().length; i++) { PropertyPath<?> p = parsingResult.getProjectedPaths()[i]; RowPropertyHelper.ColumnMetadata c = columns.get(p); if (!(p instanceof AggregationPropertyPath)) { Class<?> propertyType = FieldAccumulator.getOutputType(((AggregationPropertyPath) p).getAggregationFunction(), parsingResult.getProjectedTypes()[i]); int idx = columns.size(); columns.put(p, new RowPropertyHelper.ColumnMetadata(idx, "C" + idx, propertyType)); if (parsingResult.getSortFields() != null) { for (SortField sortField : parsingResult.getSortFields()) { PropertyPath<?> p = sortField.getPath(); RowPropertyHelper.ColumnMetadata c = columns.get(p); Class<?> propertyType = propertyHelper.getPrimitivePropertyType(parsingResult.getTargetEntityMetadata(), p.asArrayPath());
firstPhaseQuery.append("FROM ").append(parsingResult.getTargetEntityName()).append(' ').append(QueryStringCreator.DEFAULT_ALIAS); if (parsingResult.getWhereClause() != null) { BooleanExpr normalizedWhereClause = booleanFilterNormalizer.normalize(parsingResult.getWhereClause()); if (normalizedWhereClause == ConstantBooleanExpr.FALSE) { return new EmptyResultQuery(queryFactory, cache, queryString, namedParameters, startOffset, maxResults); if (propertyHelper.isRepeatedProperty(parsingResult.getTargetEntityMetadata(), p.asArrayPath())) { secondPhaseAccumulators.add(acc); if (((AggregationPropertyPath) p).getAggregationFunction() == AggregationFunction.COUNT) { _columns[c.getColumnIndex()] = c; secondPhaseQuery.append(" FROM ").append(parsingResult.getTargetEntityName()).append(' ').append(QueryStringCreator.DEFAULT_ALIAS); String secondPhaseQueryStr = secondPhaseQuery.toString(); for (int i = 0; i < parsingResult.getProjectedPaths().length; i++) { PropertyPath<?> p = parsingResult.getProjectedPaths()[i]; RowPropertyHelper.ColumnMetadata c = columns.get(p); if (i != 0) { if (parsingResult.getSortFields() != null) { thirdPhaseQuery.append(" ORDER BY "); boolean isFirst = true; for (SortField sortField : parsingResult.getSortFields()) { if (isFirst) { isFirst = false;
FieldAccumulator[] acc) { super(parsingResult, null); this.projection = parsingResult.getProjections(); this.projectionTypes = parsingResult.getProjectedTypes(); this.sortFields = parsingResult.getSortFields(); normalizedQuery = booleanFilterNormalizer.normalize(parsingResult.getWhereClause());
public LuceneQueryParsingResult<TypeMetadata> transform(IckleParsingResult<TypeMetadata> parsingResult, Map<String, Object> namedParameters, Class<?> targetedType) { this.namedParameters = namedParameters; EntityContext entityContext = queryContextBuilder.forEntity(targetedType); fieldBridgeAndAnalyzerProvider.overrideAnalyzers(parsingResult, entityContext); queryBuilder = entityContext.get(); entityType = parsingResult.getTargetEntityMetadata(); AnalyzerReference analyzerReference = ((ExtendedSearchIntegrator) searchFactory).getAnalyzerReference(new PojoIndexedTypeIdentifier(targetedType)); if (analyzerReference.is(LuceneAnalyzerReference.class)) { entityAnalyzer = analyzerReference.unwrap(LuceneAnalyzerReference.class).getAnalyzer(); } Query query = makeQuery(parsingResult.getWhereClause()); // an all negative top level boolean query is not allowed; needs a bit of rewriting if (query instanceof BooleanQuery) { BooleanQuery booleanQuery = (BooleanQuery) query; boolean allClausesAreMustNot = booleanQuery.clauses().stream().allMatch(c -> c.getOccur() == BooleanClause.Occur.MUST_NOT); if (allClausesAreMustNot) { //It is illegal to have only must-not queries, in this case we need to add a positive clause to match everything else. BooleanQuery.Builder builder = new BooleanQuery.Builder(); for (BooleanClause clause : booleanQuery.clauses()) { builder.add(clause.getQuery(), BooleanClause.Occur.MUST_NOT); } builder.add(new MatchAllDocsQuery(), BooleanClause.Occur.FILTER); query = builder.build(); } } Sort sort = makeSort(parsingResult.getSortFields()); return new LuceneQueryParsingResult<>(query, parsingResult.getTargetEntityName(), parsingResult.getTargetEntityMetadata(), parsingResult.getProjections(), sort); }
private LuceneQueryParsingResult<TypeMetadata> transformParsingResult(IckleParsingResult<TypeMetadata> parsingResult, Map<String, Object> namedParameters) { return queryCache != null && parsingResult.getParameterNames().isEmpty() ? queryCache.get(parsingResult.getQueryString(), null, LuceneQueryParsingResult.class, (queryString, accumulators) -> transformToLuceneQueryParsingResult(parsingResult, namedParameters)) : transformToLuceneQueryParsingResult(parsingResult, namedParameters); }
protected Class<?> getTargetedClass(IckleParsingResult<?> parsingResult) { return (Class<?>) parsingResult.getTargetEntityMetadata(); }