Source:
<code>public PlanNode planTableScan(TableScanNode node, Expression predicate) { Expression deterministicPredicate = filterDeterministicConjuncts(predicate); DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.fromPredicate( metadata, session, deterministicPredicate, symbolAllocator.getTypes()); TupleDomain<ColumnHandle> simplifiedConstraint = decomposedPredicate.getTupleDomain() .transform(node.getAssignments()::get) .intersect(node.getCurrentConstraint()); List<TableLayoutResult> layouts = metadata.getLayouts( session, node.getTable(), new Constraint<>(simplifiedConstraint, bindings -> true), Optional.of(ImmutableSet.copyOf(node.getAssignments().values()))); layouts = layouts.stream() <START> .filter(layout -> hasAllNeededOutputs(layout, node)) <END> .collect(toImmutableList()); if (layouts.isEmpty()) { return new ValuesNode(idAllocator.getNextId(), node.getOutputSymbols(), ImmutableList.of()); } TableLayoutResult layout = layouts.get(0); TableScanNode result = new TableScanNode( node.getId(), node.getTable(), node.getOutputSymbols(), node.getAssignments(), Optional.of(layout.getLayout().getHandle()), simplifiedConstraint.intersect(layout.getLayout().getPredicate()), Optional.ofNullable(node.getOriginalConstraint()).orElse(predicate)); Map<ColumnHandle, Symbol> assignments = ImmutableBiMap.copyOf(node.getAssignments()).inverse(); Expression resultingPredicate = combineConjuncts( decomposedPredicate.getRemainingExpression(), filterNonDeterministicConjuncts(predicate), DomainTranslator.toPredicate(layout.getUnenforcedConstraint().transform(assignments::get))); if (!BooleanLiteral.TRUE_LITERAL.equals(resultingPredicate)) { return new FilterNode(idAllocator.getNextId(), result, resultingPredicate); } return result; }</code><technical_language>This if (layouts.isEmpty()) { return new ValuesNode(idAlloc..... If layout hasAllNeededOutputs, fail. check "no layouts empty TS create values". check "no layout satisfying needed outputs .. fail" AddExchanges for ref</technical_language>

Target:
public PlanNode planTableScan(TableScanNode node, Expression predicate) { Expression deterministicPredicate = filterDeterministicConjuncts(predicate); DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.fromPredicate( metadata, session, deterministicPredicate, symbolAllocator.getTypes()); TupleDomain<ColumnHandle> simplifiedConstraint = decomposedPredicate.getTupleDomain() .transform(node.getAssignments()::get) .intersect(node.getCurrentConstraint()); List<TableLayoutResult> layouts = metadata.getLayouts( session, node.getTable(), new Constraint<>(simplifiedConstraint, bindings -> true), Optional.of(ImmutableSet.copyOf(node.getAssignments().values()))); if (layouts.isEmpty()) { return new ValuesNode(idAllocator.getNextId(), node.getOutputSymbols(), ImmutableList.of()); } layouts = layouts.stream() .filter(layout -> layout.hasAllOutputs(node)) .collect(toImmutableList()); TableLayoutResult layout = layouts.get(0); TableScanNode result = new TableScanNode( node.getId(), node.getTable(), node.getOutputSymbols(), node.getAssignments(), Optional.of(layout.getLayout().getHandle()), simplifiedConstraint.intersect(layout.getLayout().getPredicate()), Optional.ofNullable(node.getOriginalConstraint()).orElse(predicate)); Map<ColumnHandle, Symbol> assignments = ImmutableBiMap.copyOf(node.getAssignments()).inverse(); Expression resultingPredicate = combineConjuncts( decomposedPredicate.getRemainingExpression(), filterNonDeterministicConjuncts(predicate), DomainTranslator.toPredicate(layout.getUnenforcedConstraint().transform(assignments::get))); if (!BooleanLiteral.TRUE_LITERAL.equals(resultingPredicate)) { return new FilterNode(idAllocator.getNextId(), result, resultingPredicate); } return result; }