/** * Updates a given user limit based on the number of conditions that can not be fulfilled by the backend query, i.e. the query * is not fitted and these remaining conditions must be enforced by filtering in-memory. By filtering in memory, we will discard * results returned from the backend and hence we should increase the limit to account for this "waste" in order to not have * to adjust the limit too often in {@link com.thinkaurelius.titan.graphdb.query.LimitAdjustingIterator}. * * @param remainingConditions * @param baseLimit * @return */ private int computeLimit(int remainingConditions, int baseLimit) { if (baseLimit==Query.NO_LIMIT) return baseLimit; assert baseLimit>0; baseLimit = Math.max(baseLimit,Math.min(HARD_MAX_LIMIT, QueryUtil.adjustLimitForTxModifications(tx, remainingConditions, baseLimit))); assert baseLimit>0; return baseLimit; }
private static final Map.Entry<Condition,Collection<Object>> getEqualityConditionValues(Condition<TitanElement> condition, RelationType type) { for (Condition c : condition.getChildren()) { if (c instanceof Or) { Map.Entry<RelationType,Collection> orEqual = QueryUtil.extractOrCondition((Or)c); if (orEqual!=null && orEqual.getKey().equals(type) && !orEqual.getValue().isEmpty()) { return new AbstractMap.SimpleImmutableEntry(c,orEqual.getValue()); } } else if (c instanceof PredicateCondition) { PredicateCondition<RelationType, TitanRelation> atom = (PredicateCondition)c; if (atom.getKey().equals(type) && atom.getPredicate()==Cmp.EQUAL && atom.getValue()!=null) { return new AbstractMap.SimpleImmutableEntry(c,ImmutableList.of(atom.getValue())); } } } return null; }
public BaseVertexCentricQuery(Condition<TitanRelation> condition, Direction direction, List<BackendQueryHolder<SliceQuery>> queries, OrderList orders, int limit) { super(limit); Preconditions.checkArgument(condition != null && queries != null && direction != null); Preconditions.checkArgument(QueryUtil.isQueryNormalForm(condition) && limit>=0); this.condition = condition; this.queries = queries; this.orders = orders; this.direction=direction; }
And<E> conditions = new And<E>(constraints.size() + 4); for (PredicateCondition<String, E> atom : constraints) { RelationType type = getType(tx, atom.getKey()); if (values.isEmpty()) continue; //Simply ignore since trivially satisfied for (Object invalue : values) addConstraint(type, Cmp.NOT_EQUAL, invalue, conditions, tx); } else { Preconditions.checkArgument(predicate == Contain.IN); return null; //Cannot be satisfied } if (values.size() == 1) { addConstraint(type, Cmp.EQUAL, values.iterator().next(), conditions, tx); } else { Or<E> nested = new Or<E>(values.size()); for (Object invalue : values) addConstraint(type, Cmp.EQUAL, invalue, nested, tx); conditions.add(nested); addConstraint(type, predicate, value, conditions, tx);
And<TitanElement> conditions = QueryUtil.constraints2QNF(tx, constraints); if (conditions == null) return GraphCentricQuery.emptyQuery(resultType); indexLimit = limit == Query.NO_LIMIT ? DEFAULT_NO_LIMIT : Math.min(MAX_BASE_LIMIT, limit); indexLimit = Math.min(HARD_MAX_LIMIT, QueryUtil.adjustLimitForTxModifications(tx, coveredClauses.size(), indexLimit)); jointQuery.setLimit(indexLimit); query = new BackendQueryHolder<JointIndexQuery>(jointQuery, coveredClauses.size()==conditions.numChildren(), isSorted);
And<TitanRelation> conditions = QueryUtil.constraints2QNF(tx, constraints); if (conditions == null) return BaseVertexCentricQuery.emptyQuery(); InternalRelationType type = QueryUtil.getType(tx, typeName); if (type==null) continue; Preconditions.checkArgument(!querySystem || (type instanceof SystemRelationType),"Can only query for system types: %s",type); return new BaseVertexCentricQuery(QueryUtil.simplifyQNF(conditions), dir, queries, orders, limit);
@Override public Iterable<VertexLabel> getVertexLabels() { return Iterables.filter(QueryUtil.getVertices(transaction, BaseKey.SchemaCategory, TitanSchemaCategory.VERTEXLABEL), VertexLabel.class); }
protected boolean hasAllCanonicalTypes() { if (types.length==0) return false; for (String typeName : types) { InternalRelationType type = QueryUtil.getType(tx, typeName); if (type!=null && !type.isPropertyKey() && !type.multiplicity().isUnique(dir)) return false; } return true; }
private static final boolean isQNFLiteralOrNot(Condition<?> condition) { if (condition instanceof Not) { Condition child = ((Not) condition).getChild(); if (!isQNFLiteral(child)) return false; else if (child instanceof PredicateCondition) { return !((PredicateCondition) child).getPredicate().hasNegation(); } else return true; } else return isQNFLiteral(condition); }
/** * Query-normal-form (QNF) for Titan is a variant of CNF (conjunctive normal form) with negation inlined where possible * * @param condition * @return */ public static boolean isQueryNormalForm(Condition<?> condition) { if (isQNFLiteralOrNot(condition)) return true; else if (condition instanceof And) { for (Condition<?> child : ((And<?>) condition).getChildren()) { if (isQNFLiteralOrNot(child)) continue; else if (child instanceof Or) { for (Condition<?> child2 : ((Or<?>) child).getChildren()) { if (!isQNFLiteralOrNot(child2)) return false; } } else return false; } return true; } else return false; }
List<Object> resultSet = QueryUtil.processIntersectingRetrievals(retrievals, indexQuery.getLimit()); iter = com.google.common.collect.Iterators.transform(resultSet.iterator(), getConversionFunction(query.getResultType())); } else {
And<TitanElement> conditions = QueryUtil.constraints2QNF(tx, constraints); if (conditions == null) return GraphCentricQuery.emptyQuery(resultType); indexLimit = limit == Query.NO_LIMIT ? DEFAULT_NO_LIMIT : Math.min(MAX_BASE_LIMIT, limit); indexLimit = Math.min(HARD_MAX_LIMIT, QueryUtil.adjustLimitForTxModifications(tx, coveredClauses.size(), indexLimit)); jointQuery.setLimit(indexLimit); query = new BackendQueryHolder<JointIndexQuery>(jointQuery, coveredClauses.size()==conditions.numChildren(), isSorted);
And<TitanRelation> conditions = QueryUtil.constraints2QNF(tx, constraints); if (conditions == null) return BaseVertexCentricQuery.emptyQuery(); InternalRelationType type = QueryUtil.getType(tx, typeName); if (type==null) continue; Preconditions.checkArgument(!querySystem || (type instanceof SystemRelationType),"Can only query for system types: %s",type); return new BaseVertexCentricQuery(QueryUtil.simplifyQNF(conditions), dir, queries, orders, limit);
@Override public Iterable<TitanGraphIndex> getGraphIndexes(final Class<? extends Element> elementType) { return Iterables.transform(Iterables.filter(Iterables.transform( QueryUtil.getVertices(transaction, BaseKey.SchemaCategory, TitanSchemaCategory.GRAPHINDEX), new Function<TitanVertex, IndexType>() { @Nullable @Override public IndexType apply(@Nullable TitanVertex titanVertex) { assert titanVertex instanceof TitanSchemaVertex; return ((TitanSchemaVertex) titanVertex).asIndexType(); } }), new Predicate<IndexType>() { @Override public boolean apply(@Nullable IndexType indexType) { return indexType.getElement().subsumedBy(elementType); } }), new Function<IndexType, TitanGraphIndex>() { @Nullable @Override public TitanGraphIndex apply(@Nullable IndexType indexType) { return new TitanGraphIndexWrapper(indexType); } }); }
And<E> conditions = new And<E>(constraints.size() + 4); for (PredicateCondition<String, E> atom : constraints) { RelationType type = getType(tx, atom.getKey()); if (values.isEmpty()) continue; //Simply ignore since trivially satisfied for (Object invalue : values) addConstraint(type, Cmp.NOT_EQUAL, invalue, conditions, tx); } else { Preconditions.checkArgument(predicate == Contain.IN); return null; //Cannot be satisfied } if (values.size() == 1) { addConstraint(type, Cmp.EQUAL, values.iterator().next(), conditions, tx); } else { Or<E> nested = new Or<E>(values.size()); for (Object invalue : values) addConstraint(type, Cmp.EQUAL, invalue, nested, tx); conditions.add(nested); addConstraint(type, predicate, value, conditions, tx);
private boolean hasAllCanonicalTypes() { for (String typeName : types) { InternalRelationType type = QueryUtil.getType(tx, typeName); if (type==null) continue; if (!type.getMultiplicity().isUnique(dir)) return false; } return true; }
private static final boolean isQNFLiteralOrNot(Condition<?> condition) { if (condition instanceof Not) { Condition child = ((Not) condition).getChild(); if (!isQNFLiteral(child)) return false; else if (child instanceof PredicateCondition) { return !((PredicateCondition) child).getPredicate().hasNegation(); } else return true; } else return isQNFLiteral(condition); }
/** * Query-normal-form (QNF) for Titan is a variant of CNF (conjunctive normal form) with negation inlined where possible * * @param condition * @return */ public static boolean isQueryNormalForm(Condition<?> condition) { if (isQNFLiteralOrNot(condition)) return true; else if (condition instanceof And) { for (Condition<?> child : ((And<?>) condition).getChildren()) { if (isQNFLiteralOrNot(child)) continue; else if (child instanceof Or) { for (Condition<?> child2 : ((Or<?>) child).getChildren()) { if (!isQNFLiteralOrNot(child2)) return false; } } else return false; } return true; } else return false; }
List<Object> resultSet = QueryUtil.processIntersectingRetrievals(retrievals, indexQuery.getLimit()); iter = Iterators.transform(resultSet.iterator(), getConversionFunction(query.getResultType())); } else {
public IndexQuery(String store, Condition condition, ImmutableList<OrderEntry> orders, int limit) { super(limit); Preconditions.checkNotNull(store); Preconditions.checkNotNull(condition); Preconditions.checkArgument(orders != null); Preconditions.checkArgument(QueryUtil.isQueryNormalForm(condition)); this.condition = condition; this.orders = orders; this.store = store; this.hashcode = new HashCodeBuilder().append(condition).append(store).append(orders).append(limit).toHashCode(); }