public Object visit(AbstractDataFilter filter, Object rawContext) { VisitationContext context = (VisitationContext) rawContext; if (DataValueBean.isLargeValue(filter.getOperand())) { throw new InternalException( "Inlined data filter evaluation is not supported for big data values."); } final boolean isPrefetchHint = filter instanceof DataPrefetchHint; final boolean isFilterUsedInAndTerm = isAndTerm(context); final boolean isIsNullFilter = isIsNullFilter(filter); // join data_value table at most once for every dataID involved with the query, this // join will eventually be reused by successive DataFilters targeting the same // dataID (especially needed for ORed predicate to prevent combinatorial explosion) Pair joinKey = new Pair(Integer.valueOf(filter.getFilterMode()), new DataAttributeKey(filter)); Join dvJoin = (Join) dataJoinMapping.get(joinKey); // collect qualifying data OIDs Map<Long, IData> dataMap = findAllDataRtOids(filter.getDataID(), context.getEvaluationContext().getModelManager()); DataFilterExtension dataFilterExtension = SpiUtils.createDataFilterExtension(dataMap); final DataFilterExtensionContext dataFilterExtensionContext = context.getDataFilterExtensionContext(); if (null == dvJoin) { // first use of this specific dataID, setup join // a dummy queryDescriptor needed here QueryDescriptor queryDescriptor = QueryDescriptor.from(ProcessInstanceBean.class) .select( ProcessInstanceBean.FIELD__OID, ProcessInstanceBean.FIELD__SCOPE_PROCESS_INSTANCE); JoinFactory joinFactory = new JoinFactory(context); dvJoin = dataFilterExtension.createDvJoin( queryDescriptor, filter, dataJoinMapping.size() + 1, dataFilterExtensionContext, isFilterUsedInAndTerm, joinFactory); // use INNER JOIN if both is valid // * filter is used in an AND term // * filter is NOT prefetch hint // otherwise use LEFT OUTER JOIN dvJoin.setRequired(isFilterUsedInAndTerm && !isPrefetchHint && !isIsNullFilter); if (dataFilterExtensionContext.useDistinct()) { context.useDistinct(dataFilterExtensionContext.useDistinct()); } dataJoinMapping.put(joinKey, dvJoin); AndTerm andTerm = new AndTerm(); dataFilterExtension.appendDataIdTerm(andTerm, dataMap, dvJoin, filter); if (andTerm.getParts().size() != 0) { dvJoin.where(andTerm); } } else { // if join already exists // * and filter is used in an AND term // * and filter is NOT prefetch hint // then force join to be an INNER JOIN // otherwise leave it as it is if (isFilterUsedInAndTerm && !isPrefetchHint && !isIsNullFilter) { dvJoin.setRequired(true); } } if (isPrefetchHint) { final List<FieldRef> selectExtension = context.getSelectExtension(); selectExtension.addAll(dataFilterExtension.getPrefetchSelectExtension(dvJoin)); return NOTHING; } else { return dataFilterExtension.createPredicateTerm( dvJoin, filter, dataMap, dataFilterExtensionContext); } }