Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VerifyException during ordering calculation for IntersectionOnValuesPlan #2883

Open
alecgrieser opened this issue Aug 16, 2024 · 0 comments
Open

Comments

@alecgrieser
Copy link
Contributor

I ran into a planner VerifyException in a test query when trying to determine the ordering property on an intersection on values plan. I was able to reproduce it fairly reliably in the FDBSimpleQueryGraphTest with a test for a query like:

SELECT R.rest_no
   FROM RestaurantRecord AS R
   WHERE R.name IN $nameList
       AND EXISTS (SELECT t.value FROM R.tags AS t WHERE t.value = $tagValue)

This error seems to only show up when there's an index on concat(field("name"), field("tags", FanOut).nest("value")). I believe it's trying to evaluate the query by issuing one index scan of the index for each entry in nameList and then merge them together using an intersection plan, but there are problems getting the intersection plan to work.

        final Index index = new Index("Restaurant$name-tagValue", Key.Expressions.concat(
                Key.Expressions.field("name"),
                Key.Expressions.field("tags").nest(Key.Expressions.field("values", KeyExpression.FanType.FanOut).nest("value"))
        ));
        RecordMetaDataHook hook = metaDataBuilder -> metaDataBuilder.addIndex("RestaurantRecord", index);
        CascadesPlanner cascadesPlanner = setUpWithNullableArray(hook);

        final var nameValueParam = "name";
        final var tagValueParam = "t";
        final var plan = planGraph(
                () -> {
                    var qun = fullTypeScan(cascadesPlanner.getRecordMetaData(), "RestaurantRecord");

                    final var explodeTagsQun = Quantifier.forEach(Reference.of(new ExplodeExpression(FieldValue.ofFieldName(qun.getFlowedObjectValue(), "tags"))));
                    final var existentialQun = Quantifier.existential(Reference.of(GraphExpansion.builder()
                            .addQuantifier(explodeTagsQun)
                            .addResultColumn(projectColumn(explodeTagsQun.getFlowedObjectValue(), "value"))
                            .addPredicate(new ValuePredicate(FieldValue.ofFieldName(explodeTagsQun.getFlowedObjectValue(), "value"),
                                    new Comparisons.ParameterComparison(Comparisons.Type.EQUALS, tagValueParam)))
                            .build()
                            .buildSelect()));

                    qun = Quantifier.forEach(Reference.of(GraphExpansion.builder()
                            .addQuantifier(qun)
                            .addQuantifier(existentialQun)
                            .addPredicate(new ValuePredicate(FieldValue.ofFieldName(qun.getFlowedObjectValue(), "name"), new Comparisons.ParameterComparison(Comparisons.Type.IN, nameValueParam)))
                            .addPredicate(new ExistsPredicate(existentialQun.getAlias()))
                            .addResultColumn(projectColumn(qun.getFlowedObjectValue(), "rest_no"))
                            .build()
                            .buildSelect()));
                    return Reference.of(LogicalSortExpression.unsorted(qun));
                });

Here's a stack trace from trying to plan that query in the test:

com.google.common.base.VerifyException
	at com.google.common.base.Verify.verify(Verify.java:102)
	at com.apple.foundationdb.record.query.plan.cascades.Ordering$SetOperationsOrdering.lambda$applyComparisonKey$2(Ordering.java:1335)
	at com.apple.foundationdb.record.query.plan.cascades.debug.Debugger.lambda$sanityCheck$0(Debugger.java:118)
	at com.apple.foundationdb.record.query.plan.cascades.debug.Debugger.withDebugger(Debugger.java:107)
	at com.apple.foundationdb.record.query.plan.cascades.debug.Debugger.sanityCheck(Debugger.java:116)
	at com.apple.foundationdb.record.query.plan.cascades.Ordering$SetOperationsOrdering.applyComparisonKey(Ordering.java:1335)
	at com.apple.foundationdb.record.query.plan.cascades.properties.OrderingProperty$OrderingVisitor.deriveForDistinctSetOperationFromOrderings(OrderingProperty.java:663)
	at com.apple.foundationdb.record.query.plan.cascades.properties.OrderingProperty$OrderingVisitor.visitIntersectionOnValuesPlan(OrderingProperty.java:296)
        at com.apple.foundationdb.record.query.plan.cascades.properties.OrderingProperty$OrderingVisitor.visitIntersectionOnValuesPlan(OrderingProperty.java:116)
	at com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanVisitor.lambda$static$13(RecordQueryPlanVisitor.java:24)
	at com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanVisitor.visit(RecordQueryPlanVisitor.java:168)
	at com.apple.foundationdb.record.query.plan.cascades.PropertiesMap.computePropertyValue(PropertiesMap.java:168)
	at com.apple.foundationdb.record.query.plan.cascades.PropertiesMap.update(PropertiesMap.java:110)
	at com.apple.foundationdb.record.query.plan.cascades.PropertiesMap.getPlanPartitions(PropertiesMap.java:199)
	at com.apple.foundationdb.record.query.plan.cascades.Reference.getPlanPartitions(Reference.java:383)
	at com.apple.foundationdb.record.query.plan.cascades.matching.structure.Extractor.lambda$new$0(Extractor.java:40)
	at com.apple.foundationdb.record.query.plan.cascades.matching.structure.Extractor.unapply(Extractor.java:51)
	at com.apple.foundationdb.record.query.plan.cascades.matching.structure.TypedMatcherWithExtractAndDownstream.lambda$bindMatchesSafely$0(TypedMatcherWithExtractAndDownstream.java:67)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:271)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
	at com.apple.foundationdb.record.query.plan.cascades.matching.structure.ListMatcher.bindMatchesSafely(ListMatcher.java:66)
	at com.apple.foundationdb.record.query.plan.cascades.matching.structure.ListMatcher.bindMatchesSafely(ListMatcher.java:44)
	at com.apple.foundationdb.record.query.plan.cascades.matching.structure.BindingMatcher.bindMatches(BindingMatcher.java:94)
	at com.apple.foundationdb.record.query.plan.cascades.matching.structure.TypedMatcherWithExtractAndDownstream.lambda$bindMatchesSafely$0(TypedMatcherWithExtractAndDownstream.java:67)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:271)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
	at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at com.apple.foundationdb.record.query.plan.cascades.CascadesPlanner$AbstractTransform.execute(CascadesPlanner.java:862)
	at com.apple.foundationdb.record.query.plan.cascades.CascadesPlanner.planPartial(CascadesPlanner.java:405)
	at com.apple.foundationdb.record.query.plan.cascades.CascadesPlanner.planGraph(CascadesPlanner.java:344)
	at com.apple.foundationdb.record.provider.foundationdb.query.FDBRecordStoreQueryTestBase.planGraph(FDBRecordStoreQueryTestBase.java:644)
	at com.apple.foundationdb.record.provider.foundationdb.query.FDBRecordStoreQueryTestBase.planGraph(FDBRecordStoreQueryTestBase.java:631)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant