Package com.foundationdb.server.test.it.qp

Source Code of com.foundationdb.server.test.it.qp.FlattenIT

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.server.test.it.qp;

import com.foundationdb.qp.expression.IndexBound;
import com.foundationdb.qp.expression.IndexKeyRange;
import com.foundationdb.qp.operator.Cursor;
import com.foundationdb.qp.operator.IndexScanSelector;
import com.foundationdb.qp.operator.Operator;
import com.foundationdb.qp.row.Row;
import com.foundationdb.qp.rowtype.IndexRowType;
import com.foundationdb.qp.rowtype.RowType;
import com.foundationdb.server.api.dml.SetColumnSelector;
import org.junit.Test;

import java.util.Arrays;
import java.util.EnumSet;

import static com.foundationdb.qp.operator.API.*;
import static com.foundationdb.qp.operator.API.FlattenOption.KEEP_CHILD;
import static com.foundationdb.qp.operator.API.FlattenOption.KEEP_PARENT;
import static com.foundationdb.qp.operator.API.JoinType.*;
import static org.junit.Assert.assertTrue;

public class FlattenIT extends OperatorITBase
{
    @Override
    protected void setupPostCreateSchema() {
        super.setupPostCreateSchema();
        Row[] dbWithOrphans = new Row[]{
            row(customer, 1L, "northbridge"),
            row(customer, 2L, "foundation"),
            row(customer, 4L, "highland"),
            row(customer, 5L, "matrix"), // customer 5 is for testing bug 792102
            row(order, 11L, 1L, "ori"),
            row(order, 12L, 1L, "david"),
            row(order, 21L, 2L, "tom"),
            row(order, 22L, 2L, "jack"),
            row(order, 31L, 3L, "peter"),
            row(order, 51L, 5L, "yuval"),
            row(item, 111L, 11L),
            row(item, 112L, 11L),
            row(item, 121L, 12L),
            row(item, 122L, 12L),
            row(item, 211L, 21L),
            row(item, 212L, 21L),
            row(item, 221L, 22L),
            row(item, 222L, 22L),
            // orphans
            row(item, 311L, 31L),
            row(item, 312L, 31L),
            // Bug 837706
            row(address, 41L, 4L, "560 Harrison"),
            // Bug 1018206
            row(customer, 6L, "nea"),
            row(order, 61L, 6L, "mike"),
            row(order, 62L, 6L, "padraig"),
            row(item, 621L, 62L),
        };
        use(dbWithOrphans);
    }

    // IllegalArumentException tests

    @Test(expected = IllegalArgumentException.class)
    public void testNullParent()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                            null,
                            orderRowType,
                            INNER_JOIN,
                            EnumSet.noneOf(FlattenOption.class));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testNullChild()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                            customerRowType,
                            null,
                            INNER_JOIN,
                            EnumSet.noneOf(FlattenOption.class));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testParentChild_Unrelated()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                            addressRowType,
                            orderRowType,
                            INNER_JOIN,
                            EnumSet.noneOf(FlattenOption.class));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testParentChild_SameType()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                            orderRowType,
                            orderRowType,
                            INNER_JOIN,
                            EnumSet.noneOf(FlattenOption.class));
    }

    @Test
    public void testParentChild_BaseTables()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                            customerRowType,
                            orderRowType,
                            INNER_JOIN,
                            EnumSet.noneOf(FlattenOption.class));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testParentChild_UpsideDown()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                            orderRowType,
                            customerRowType,
                            INNER_JOIN,
                            EnumSet.noneOf(FlattenOption.class));
    }

    @Test
    public void testParentChild_FlattenedParent()
    {
        Operator co =
            flatten_HKeyOrdered(groupScan_Default(coi),
                               customerRowType,
                               orderRowType,
                               INNER_JOIN,
                               EnumSet.noneOf(FlattenOption.class));
        flatten_HKeyOrdered(groupScan_Default(coi),
                           co.rowType(),
                           itemRowType,
                           INNER_JOIN,
                           EnumSet.noneOf(FlattenOption.class));
    }

    @Test
    public void testParentChild_FlattenedChild()
    {
        Operator oi =
            flatten_HKeyOrdered(groupScan_Default(coi),
                               orderRowType,
                               itemRowType,
                               INNER_JOIN,
                               EnumSet.noneOf(FlattenOption.class));
        flatten_HKeyOrdered(groupScan_Default(coi),
                           customerRowType,
                           oi.rowType(),
                           INNER_JOIN,
                           EnumSet.noneOf(FlattenOption.class));
    }

    @Test
    public void testParentChild_GrandParent()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                           customerRowType,
                           itemRowType,
                           INNER_JOIN,
                           EnumSet.noneOf(FlattenOption.class));
    }

    @Test(expected = IllegalArgumentException.class)
    public void nullJoinType()
    {
        flatten_HKeyOrdered(groupScan_Default(coi),
                            customerRowType,
                            orderRowType,
                            null,
                            EnumSet.noneOf(FlattenOption.class));
    }

    // Tests of join behavior

    @Test
    public void testInnerJoinCO()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                customerRowType,
                orderRowType,
                INNER_JOIN);
        RowType coRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(coRowType, 1L, "northbridge", 11L, 1L, "ori"),
            row(itemRowType, 111L, 11L),
            row(itemRowType, 112L, 11L),
            row(coRowType, 1L, "northbridge", 12L, 1L, "david"),
            row(itemRowType, 121L, 12L),
            row(itemRowType, 122L, 12L),
            row(coRowType, 2L, "foundation", 21L, 2L, "tom"),
            row(itemRowType, 211L, 21L),
            row(itemRowType, 212L, 21L),
            row(coRowType, 2L, "foundation", 22L, 2L, "jack"),
            row(itemRowType, 221L, 22L),
            row(itemRowType, 222L, 22L),
            row(itemRowType, 311L, 31L),
            row(itemRowType, 312L, 31L),
            row(coRowType, 5L, "matrix", 51L, 5L, "yuval"),
            row(coRowType, 6L, "nea", 61L, 6L, "mike"),
            row(coRowType, 6L, "nea", 62L, 6L, "padraig"),
            row(itemRowType, 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testInnerJoinOI()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                orderRowType,
                itemRowType,
                INNER_JOIN);
        RowType oiRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(customerRowType, 1L, "northbridge"),
            row(oiRowType, 11L, 1L, "ori", 111L, 11L),
            row(oiRowType, 11L, 1L, "ori", 112L, 11L),
            row(oiRowType, 12L, 1L, "david", 121L, 12L),
            row(oiRowType, 12L, 1L, "david", 122L, 12L),
            row(customerRowType, 2L, "foundation"),
            row(oiRowType, 21L, 2L, "tom", 211L, 21L),
            row(oiRowType, 21L, 2L, "tom", 212L, 21L),
            row(oiRowType, 22L, 2L, "jack", 221L, 22L),
            row(oiRowType, 22L, 2L, "jack", 222L, 22L),
            row(oiRowType, 31L, 3L, "peter", 311L, 31L),
            row(oiRowType, 31L, 3L, "peter", 312L, 31L),
            row(customerRowType, 4L, "highland"),
            row(customerRowType, 5L, "matrix"),
            row(customerRowType, 6L, "nea"),
            row(oiRowType, 62L, 6L, "padraig", 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testLeftJoinCO()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                customerRowType,
                orderRowType,
                LEFT_JOIN);
        RowType coRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(oKey(1L, 11L), coRowType, 1L, "northbridge", 11L, 1L, "ori"),
            row(iKey(1L, 11L, 111L), itemRowType, 111L, 11L),
            row(iKey(1L, 11L, 112L), itemRowType, 112L, 11L),
            row(coRowType, 1L, "northbridge", 12L, 1L, "david"),
            row(itemRowType, 121L, 12L),
            row(itemRowType, 122L, 12L),
            row(coRowType, 2L, "foundation", 21L, 2L, "tom"),
            row(itemRowType, 211L, 21L),
            row(itemRowType, 212L, 21L),
            row(coRowType, 2L, "foundation", 22L, 2L, "jack"),
            row(itemRowType, 221L, 22L),
            row(itemRowType, 222L, 22L),
            row(itemRowType, 311L, 31L),
            row(itemRowType, 312L, 31L),
            row(oKey(4L, null), coRowType, 4L, "highland", null, null, null),
            row(coRowType, 5L, "matrix", 51L, 5L, "yuval"),
            row(coRowType, 6L, "nea", 61L, 6L, "mike"),
            row(coRowType, 6L, "nea", 62L, 6L, "padraig"),
            row(itemRowType, 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testLeftJoinOI()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                orderRowType,
                itemRowType,
                LEFT_JOIN);
        RowType oiRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(customerRowType, 1L, "northbridge"),
            row(oiRowType, 11L, 1L, "ori", 111L, 11L),
            row(oiRowType, 11L, 1L, "ori", 112L, 11L),
            row(oiRowType, 12L, 1L, "david", 121L, 12L),
            row(oiRowType, 12L, 1L, "david", 122L, 12L),
            row(customerRowType, 2L, "foundation"),
            row(oiRowType, 21L, 2L, "tom", 211L, 21L),
            row(oiRowType, 21L, 2L, "tom", 212L, 21L),
            row(oiRowType, 22L, 2L, "jack", 221L, 22L),
            row(oiRowType, 22L, 2L, "jack", 222L, 22L),
            row(oiRowType, 31L, 3L, "peter", 311L, 31L),
            row(oiRowType, 31L, 3L, "peter", 312L, 31L),
            row(customerRowType, 4L, "highland"),
            row(customerRowType, 5L, "matrix"),
            row(oiRowType, 51L, 5L, "yuval", null, null),
            row(customerRowType, 6L, "nea"),
            row(oiRowType, 61L, 6L, "mike", null, null),
            row(oiRowType, 62L, 6L, "padraig", 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testRightJoinCO()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                customerRowType,
                orderRowType,
                RIGHT_JOIN);
        RowType coRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(coRowType, 1L, "northbridge", 11L, 1L, "ori"),
            row(itemRowType, 111L, 11L),
            row(itemRowType, 112L, 11L),
            row(coRowType, 1L, "northbridge", 12L, 1L, "david"),
            row(itemRowType, 121L, 12L),
            row(itemRowType, 122L, 12L),
            row(coRowType, 2L, "foundation", 21L, 2L, "tom"),
            row(itemRowType, 211L, 21L),
            row(itemRowType, 212L, 21L),
            row(coRowType, 2L, "foundation", 22L, 2L, "jack"),
            row(itemRowType, 221L, 22L),
            row(itemRowType, 222L, 22L),
            row(coRowType, null, null, 31L, 3L, "peter"),
            row(itemRowType, 311L, 31L),
            row(itemRowType, 312L, 31L),
            row(coRowType, 5L, "matrix", 51L, 5L, "yuval"),
            row(coRowType, 6L, "nea", 61L, 6L, "mike"),
            row(coRowType, 6L, "nea", 62L, 6L, "padraig"),
            row(itemRowType, 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testRightJoinOI()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                orderRowType,
                itemRowType,
                RIGHT_JOIN);
        RowType oiRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(customerRowType, 1L, "northbridge"),
            row(oiRowType, 11L, 1L, "ori", 111L, 11L),
            row(oiRowType, 11L, 1L, "ori", 112L, 11L),
            row(oiRowType, 12L, 1L, "david", 121L, 12L),
            row(oiRowType, 12L, 1L, "david", 122L, 12L),
            row(customerRowType, 2L, "foundation"),
            row(oiRowType, 21L, 2L, "tom", 211L, 21L),
            row(oiRowType, 21L, 2L, "tom", 212L, 21L),
            row(oiRowType, 22L, 2L, "jack", 221L, 22L),
            row(oiRowType, 22L, 2L, "jack", 222L, 22L),
            row(oiRowType, 31L, 3L, "peter", 311L, 31L),
            row(oiRowType, 31L, 3L, "peter", 312L, 31L),
            row(customerRowType, 4L, "highland"),
            row(customerRowType, 5L, "matrix"),
            row(customerRowType, 6L, "nea"),
            row(oiRowType, 62L, 6L, "padraig", 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testFullJoinCO()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                customerRowType,
                orderRowType,
                FULL_JOIN);
        RowType coRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(coRowType, 1L, "northbridge", 11L, 1L, "ori"),
            row(itemRowType, 111L, 11L),
            row(itemRowType, 112L, 11L),
            row(coRowType, 1L, "northbridge", 12L, 1L, "david"),
            row(itemRowType, 121L, 12L),
            row(itemRowType, 122L, 12L),
            row(coRowType, 2L, "foundation", 21L, 2L, "tom"),
            row(itemRowType, 211L, 21L),
            row(itemRowType, 212L, 21L),
            row(coRowType, 2L, "foundation", 22L, 2L, "jack"),
            row(itemRowType, 221L, 22L),
            row(itemRowType, 222L, 22L),
            row(coRowType, null, null, 31L, 3L, "peter"),
            row(itemRowType, 311L, 31L),
            row(itemRowType, 312L, 31L),
            row(coRowType, 4L, "highland", null, null, null),
            row(coRowType, 5L, "matrix", 51L, 5L, "yuval"),
            row(coRowType, 6L, "nea", 61L, 6L, "mike"),
            row(coRowType, 6L, "nea", 62L, 6L, "padraig"),
            row(itemRowType, 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testFullJoinOI()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                orderRowType,
                itemRowType,
                FULL_JOIN);
        RowType oiRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(customerRowType, 1L, "northbridge"),
            row(oiRowType, 11L, 1L, "ori", 111L, 11L),
            row(oiRowType, 11L, 1L, "ori", 112L, 11L),
            row(oiRowType, 12L, 1L, "david", 121L, 12L),
            row(oiRowType, 12L, 1L, "david", 122L, 12L),
            row(customerRowType, 2L, "foundation"),
            row(oiRowType, 21L, 2L, "tom", 211L, 21L),
            row(oiRowType, 21L, 2L, "tom", 212L, 21L),
            row(oiRowType, 22L, 2L, "jack", 221L, 22L),
            row(oiRowType, 22L, 2L, "jack", 222L, 22L),
            row(oiRowType, 31L, 3L, "peter", 311L, 31L),
            row(oiRowType, 31L, 3L, "peter", 312L, 31L),
            row(customerRowType, 4L, "highland"),
            row(customerRowType, 5L, "matrix"),
            row(oiRowType, 51L, 5L, "yuval", null, null),
            row(customerRowType, 6L, "nea"),
            row(oiRowType, 61L, 6L, "mike", null, null),
            row(oiRowType, 62L, 6L, "padraig", 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    // Tests of keep input row behavior
    // TODO: Ordering between flattened row and input child row is not well defined. They have matching hkeys,
    // TODO: e.g., for order and co.

    @Test
    public void testFullJoinCOKeepParentAndChild()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                customerRowType,
                orderRowType,
                FULL_JOIN, KEEP_PARENT, KEEP_CHILD);
        RowType coRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(customerRowType, 1L, "northbridge"),
            row(orderRowType, 11L, 1L, "ori"),
            row(coRowType, 1L, "northbridge", 11L, 1L, "ori"),
            row(itemRowType, 111L, 11L),
            row(itemRowType, 112L, 11L),
            row(orderRowType, 12L, 1L, "david"),
            row(coRowType, 1L, "northbridge", 12L, 1L, "david"),
            row(itemRowType, 121L, 12L),
            row(itemRowType, 122L, 12L),
            row(customerRowType, 2L, "foundation"),
            row(orderRowType, 21L, 2L, "tom"),
            row(coRowType, 2L, "foundation", 21L, 2L, "tom"),
            row(itemRowType, 211L, 21L),
            row(itemRowType, 212L, 21L),
            row(orderRowType, 22L, 2L, "jack"),
            row(coRowType, 2L, "foundation", 22L, 2L, "jack"),
            row(itemRowType, 221L, 22L),
            row(itemRowType, 222L, 22L),
            row(orderRowType, 31L, 3L, "peter"),
            row(coRowType, null, null, 31L, 3L, "peter"),
            row(itemRowType, 311L, 31L),
            row(itemRowType, 312L, 31L),
            row(customerRowType, 4L, "highland"),
            row(coRowType, 4L, "highland", null, null, null),
            row(customerRowType, 5L, "matrix"),
            row(orderRowType, 51L, 5L, "yuval"),
            row(coRowType, 5L, "matrix", 51L, 5L, "yuval"),
            row(customerRowType, 6L, "nea"),
            row(orderRowType, 61L, 6L, "mike"),
            row(coRowType, 6L, "nea", 61L, 6L, "mike"),
            row(orderRowType, 62L, 6L, "padraig"),
            row(coRowType, 6L, "nea", 62L, 6L, "padraig"),
            row(itemRowType, 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testFullJoinOIKeepParentAndChild()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                orderRowType,
                itemRowType,
                FULL_JOIN, KEEP_PARENT, KEEP_CHILD);
        RowType oiRowType = plan.rowType();
        Cursor cursor = cursor(plan, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(customerRowType, 1L, "northbridge"),
            row(orderRowType, 11L, 1L, "ori"),
            row(itemRowType, 111L, 11L),
            row(oiRowType, 11L, 1L, "ori", 111L, 11L),
            row(itemRowType, 112L, 11L),
            row(oiRowType, 11L, 1L, "ori", 112L, 11L),
            row(orderRowType, 12L, 1L, "david"),
            row(itemRowType, 121L, 12L),
            row(oiRowType, 12L, 1L, "david", 121L, 12L),
            row(itemRowType, 122L, 12L),
            row(oiRowType, 12L, 1L, "david", 122L, 12L),
            row(customerRowType, 2L, "foundation"),
            row(orderRowType, 21L, 2L, "tom"),
            row(itemRowType, 211L, 21L),
            row(oiRowType, 21L, 2L, "tom", 211L, 21L),
            row(itemRowType, 212L, 21L),
            row(oiRowType, 21L, 2L, "tom", 212L, 21L),
            row(orderRowType, 22L, 2L, "jack"),
            row(itemRowType, 221L, 22L),
            row(oiRowType, 22L, 2L, "jack", 221L, 22L),
            row(itemRowType, 222L, 22L),
            row(oiRowType, 22L, 2L, "jack", 222L, 22L),
            row(orderRowType, 31L, 3L, "peter"),
            row(itemRowType, 311L, 31L),
            row(oiRowType, 31L, 3L, "peter", 311L, 31L),
            row(itemRowType, 312L, 31L),
            row(oiRowType, 31L, 3L, "peter", 312L, 31L),
            row(customerRowType, 4L, "highland"),
            row(customerRowType, 5L, "matrix"),
            row(orderRowType, 51L, 5L, "yuval"),
            row(oiRowType, 51L, 5L, "yuval", null, null),
            row(customerRowType, 6L, "nea"),
            row(orderRowType, 61L, 6L, "mike"),
            row(oiRowType, 61L, 6L, "mike", null, null),
            row(orderRowType, 62L, 6L, "padraig"),
            row(itemRowType, 621L, 62L),
            row(oiRowType, 62L, 6L, "padraig", 621L, 62L),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testBug837706()
    {
        // inner join CA followed by left join CO, for a missing order. The (customer, null) row for the missing order
        // appears after the (customer, address) row, which is wrong.
        assertTrue(ordinal(customerRowType) < ordinal(orderRowType));
        assertTrue(ordinal(orderRowType) < ordinal(addressRowType));
        Operator flattenCA =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, addressRowType)),
                customerRowType,
                addressRowType,
                INNER_JOIN,
                KEEP_PARENT);
        Operator flattenCO =
            flatten_HKeyOrdered(
                flattenCA,
                customerRowType,
                orderRowType,
                LEFT_JOIN);
        Cursor cursor = cursor(flattenCO, queryContext, queryBindings);
        Row[] expected = new Row[]{
            row(flattenCO.rowType(), 1L, "northbridge", 11L, 1L, "ori"),
            row(flattenCO.rowType(), 1L, "northbridge", 12L, 1L, "david"),
            row(flattenCO.rowType(), 2L, "foundation", 21L, 2L, "tom"),
            row(flattenCO.rowType(), 2L, "foundation", 22L, 2L, "jack"),
            row(flattenCO.rowType(), 4L, "highland", null, null, null),
            row(flattenCA.rowType(), 4L, "highland", 41L, 4L, "560 Harrison"),
            row(flattenCO.rowType(), 5L, "matrix", 51L, 5L, "yuval"),
            row(flattenCO.rowType(), 6L, "nea", 61L, 6L, "mike"),
            row(flattenCO.rowType(), 6L, "nea", 62L, 6L, "padraig"),
        };
        compareRows(expected, cursor);
    }

    @Test
    public void testBug1018206()
    {
        IndexBound cnameBound = new IndexBound(row(customerNameItemOidIndexRowType, "nea"), new SetColumnSelector(0));
        IndexKeyRange cnameRange = IndexKeyRange.bounded(customerNameItemOidIndexRowType, cnameBound, true, cnameBound, true);
        IndexScanSelector indexScanSelector = IndexScanSelector.leftJoinAfter(customerNameItemOidIndexRowType.index(),
                                                                              customerRowType.table());
        Operator flatten =
            flatten_HKeyOrdered(
                ancestorLookup_Default(
                    indexScan_Default(customerNameItemOidIndexRowType, cnameRange, ordering(), indexScanSelector),
                    coi,
                    customerNameItemOidIndexRowType,
                    Arrays.asList(customerRowType, itemRowType),
                    InputPreservationOption.DISCARD_INPUT),
                customerRowType,
                itemRowType,
                LEFT_JOIN);
        Row[] expected = new Row[] {
            row(flatten.rowType(), 6L, "nea", null, null),
            row(flatten.rowType(), 6L, "nea", 621L, 62L),
        };
        compareRows(expected, cursor(flatten, queryContext, queryBindings));
    }

    @Test
    public void testCursor()
    {
        Operator plan =
            flatten_HKeyOrdered(
                filter_Default(
                    groupScan_Default(coi),
                    Arrays.asList(customerRowType, orderRowType, itemRowType)),
                orderRowType,
                itemRowType,
                FULL_JOIN);
        final RowType oiRowType = plan.rowType();
        CursorLifecycleTestCase testCase = new CursorLifecycleTestCase()
        {
            @Override
            public Row[] firstExpectedRows()
            {
                return new Row[] {
                row(customerRowType, 1L, "northbridge"),
                    row(oiRowType, 11L, 1L, "ori", 111L, 11L),
                    row(oiRowType, 11L, 1L, "ori", 112L, 11L),
                    row(oiRowType, 12L, 1L, "david", 121L, 12L),
                    row(oiRowType, 12L, 1L, "david", 122L, 12L),
                    row(customerRowType, 2L, "foundation"),
                    row(oiRowType, 21L, 2L, "tom", 211L, 21L),
                    row(oiRowType, 21L, 2L, "tom", 212L, 21L),
                    row(oiRowType, 22L, 2L, "jack", 221L, 22L),
                    row(oiRowType, 22L, 2L, "jack", 222L, 22L),
                    row(oiRowType, 31L, 3L, "peter", 311L, 31L),
                    row(oiRowType, 31L, 3L, "peter", 312L, 31L),
                    row(customerRowType, 4L, "highland"),
                    row(customerRowType, 5L, "matrix"),
                    row(oiRowType, 51L, 5L, "yuval", null, null),
                    row(customerRowType, 6L, "nea"),
                    row(oiRowType, 61L, 6L, "mike", null, null),
                    row(oiRowType, 62L, 6L, "padraig", 621L, 62L),
                };
            }
        };
        testCursorLifecycle(plan, testCase);
    }

    private String cKey(Long cid)
    {
        return String.format("{%d,%s}", customerOrdinal, hKeyValue(cid));
    }

    private String oKey(Long cid, Long oid)
    {
        return String.format("{%d,%s,%d,%s}", customerOrdinal, hKeyValue(cid), orderOrdinal, hKeyValue(oid));
    }

    private String iKey(Long cid, Long oid, Long iid)
    {
        return String.format("{%d,%s,%d,%s,%d,%s}", customerOrdinal, hKeyValue(cid), orderOrdinal, hKeyValue(oid), itemOrdinal, hKeyValue(iid));
    }

    private IndexRowType giRowType;
}
TOP

Related Classes of com.foundationdb.server.test.it.qp.FlattenIT

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.