public static double getSourceTablesSizeInBytes(PlanNode node, Context context)
    {
        return getSourceTablesSizeInBytes(node, context.getLookup(), context.getStatsProvider());
    }
@Test
    public void testGetSourceTablesSizeInBytes()
    {
        PlanBuilder planBuilder = new PlanBuilder(tester.getSession(), new PlanNodeIdAllocator(), tester.getMetadata());
        VariableReferenceExpression variable = planBuilder.variable("col");
        VariableReferenceExpression sourceVariable1 = planBuilder.variable("source1");
        VariableReferenceExpression sourceVariable2 = planBuilder.variable("soruce2");

        // missing source stats
        assertEquals(
                getSourceTablesSizeInBytes(
                        planBuilder.values(variable),
                        noLookup(),
                        node -> PlanNodeStatsEstimate.unknown()),
                NaN);

        // two source plan nodes
        PlanNodeStatsEstimate sourceStatsEstimate1 = PlanNodeStatsEstimate.builder()
                .setOutputRowCount(10)
                .build();
        PlanNodeStatsEstimate sourceStatsEstimate2 = PlanNodeStatsEstimate.builder()
                .setOutputRowCount(20)
                .build();
        assertEquals(
                getSourceTablesSizeInBytes(
                        planBuilder.union(
                                ImmutableListMultimap.<VariableReferenceExpression, VariableReferenceExpression>builder()
                                        .put(variable, sourceVariable1)
                                        .put(variable, sourceVariable2)
                                        .build(),
                                ImmutableList.of(planBuilder.tableScan(
                                                ImmutableList.of(sourceVariable1),
                                                ImmutableMap.of(sourceVariable1, new TestingColumnHandle("col"))),
                                        planBuilder.values(new PlanNodeId("valuesNode"), sourceVariable2))),
                        noLookup(),
                        node -> {
                            if (node instanceof TableScanNode) {
                                return sourceStatsEstimate1;
                            }

                            if (node instanceof ValuesNode) {
                                return sourceStatsEstimate2;
                            }

                            return PlanNodeStatsEstimate.unknown();
                        }),
                270.0);

        // join node
        assertEquals(
                getSourceTablesSizeInBytes(
                        planBuilder.join(
                                INNER,
                                planBuilder.values(sourceVariable1),
                                planBuilder.values(sourceVariable2)),
                        noLookup(),
                        node -> sourceStatsEstimate1),
                NaN);

        // unnest node
        assertEquals(
                getSourceTablesSizeInBytes(
                        planBuilder.unnest(
                                planBuilder.values(sourceVariable1),
                                ImmutableList.of(),
                                ImmutableMap.of(sourceVariable1, ImmutableList.of(sourceVariable1)),
                                Optional.empty()),
                        noLookup(),
                        node -> sourceStatsEstimate1),
                NaN);
    }