@Nonnull
    public static List<JetSqlRow> evaluate(
            @Nullable Expression<Boolean> predicate,
            @Nullable List<Expression<?>> projection,
            @Nonnull Stream<JetSqlRow> rows,
            @Nonnull ExpressionEvalContext context
    ) {
        return rows
                .map(row -> evaluate(predicate, projection, row, context))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
@Test
    public void test_evaluateWithPredicateAndProjection() {
        List<Object[]> rows = asList(new Object[]{0, "a"}, new Object[]{1, "b"}, new Object[]{2, "c"});

        Expression<Boolean> predicate = new FunctionalPredicateExpression(row -> {
            int value = row.get(0);
            return value != 1;
        });
        MultiplyFunction<?> projection =
                MultiplyFunction.create(ColumnExpression.create(0, INT), ConstantExpression.create(2, INT), INT);

        List<JetSqlRow> evaluated = ExpressionUtil.evaluate(predicate, singletonList(projection), rows.stream().map(v -> new JetSqlRow(TEST_SS, v)),
                mock(ExpressionEvalContext.class));

        assertThat(toList(evaluated, JetSqlRow::getValues)).containsExactly(new Object[]{0}, new Object[]{4});
    }