class TransformUncorrelatedInPredicateSubqueryToSemiJoin implements Rule<ApplyNode> {

    @Override
    public Result apply(ApplyNode applyNode, Captures captures, Context context)
    {
        if (applyNode.getSubqueryAssignments().size() != 1) {
            return Result.empty();
        }

        Expression expression = getOnlyElement(applyNode.getSubqueryAssignments().getExpressions());
        if (!(expression instanceof InPredicate)) {
            return Result.empty();
        }

        InPredicate inPredicate = (InPredicate) expression;
        Symbol semiJoinSymbol = getOnlyElement(applyNode.getSubqueryAssignments().getSymbols());

        SemiJoinNode replacement = new SemiJoinNode(context.getIdAllocator().getNextId(),
                applyNode.getInput(),
                applyNode.getSubquery(),
                Symbol.from(inPredicate.getValue()),
                Symbol.from(inPredicate.getValueList()),
                semiJoinSymbol,
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty());

        return Result.ofPlanNode(replacement);
    }

}