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

import static com.foundationdb.qp.operator.API.cursor;
import static com.foundationdb.qp.operator.API.groupScan_Default;
import static com.foundationdb.qp.operator.API.select_HKeyOrdered;
import static com.foundationdb.qp.operator.API.unionAll_Default;
import static com.foundationdb.qp.operator.API.union_Ordered;

import org.junit.Test;

import com.foundationdb.ais.model.Group;
import com.foundationdb.qp.operator.Operator;
import com.foundationdb.qp.row.RowBase;
import com.foundationdb.qp.rowtype.Schema;
import com.foundationdb.qp.rowtype.UserTableRowType;
import com.foundationdb.server.api.dml.scan.NewRow;
import com.foundationdb.server.test.ExpressionGenerators;
import com.foundationdb.server.types.texpressions.Comparison;

public class UnionAllIT extends OperatorITBase {

    @Override
    protected void setupCreateSchema()
    {
        t = createTable(
            "schema", "t",
            "id int not null",
            "x int",
            "primary key(id)");
        createIndex("schema", "t", "tx", "x");
        u = createTable (
                "schema", "u",
                "id int not null primary key",
                "x int");
    }

    @Override
    protected void setupPostCreateSchema()
    {
        schema = new Schema(ais());
        tRowType = schema.userTableRowType(userTable(t));
        uRowType = schema.userTableRowType(userTable(u));
        tGroupTable = group(t);
        uGroupTable = group(u);
        adapter = newStoreAdapter(schema);
        queryContext = queryContext(adapter);
        queryBindings = queryContext.createBindings();
        db = new NewRow[]{
            createNewRow(t, 1000L, 8L),
            createNewRow(t, 1001L, 9L),
            createNewRow(t, 1002L, 8L),
            createNewRow(t, 1003L, 9L),
            createNewRow(t, 1004L, 8L),
            createNewRow(t, 1005L, 9L),
            createNewRow(t, 1006L, 8L),
            createNewRow(t, 1007L, 9L),
            createNewRow(u, 1000L, 7L),
            createNewRow(u, 1001L, 9L),
            createNewRow(u, 1002L, 9L),
            createNewRow(u, 1003L, 9L)
        };
        use(db);
    }
    private int t, u;
    private UserTableRowType tRowType, uRowType;
    private Group tGroupTable, uGroupTable;
    
    @Test
    public void testBothNonEmpty()
    {
        Operator plan =
            unionAll_Default(
                select_HKeyOrdered(
                    groupScan_Default(tGroupTable),
                    tRowType,
                    ExpressionGenerators.compare(
                        ExpressionGenerators.field(tRowType, 1),
                        Comparison.EQ,
                        ExpressionGenerators.literal(8), castResolver())),
                tRowType,
                select_HKeyOrdered(
                    groupScan_Default(uGroupTable),
                    uRowType,
                    ExpressionGenerators.compare(
                        ExpressionGenerators.field(uRowType, 1),
                        Comparison.EQ,
                        ExpressionGenerators.literal(7), castResolver())),
                uRowType, 
                true);
        RowBase[] expected = new RowBase[]{
            row(tRowType, 1000L, 8L),
            row(tRowType, 1002L, 8L),
            row(tRowType, 1004L, 8L),
            row(tRowType, 1006L, 8L),
            row(uRowType, 1000L, 7L),
        };
        compareRows(expected, cursor(plan, queryContext, queryBindings));
    }
    
    @Test
    public void testOrderedNonEmpty()
    {
        Operator plan =
            union_Ordered(
                select_HKeyOrdered(
                    groupScan_Default(tGroupTable),
                    tRowType,
                    ExpressionGenerators.compare(
                        ExpressionGenerators.field(tRowType, 1),
                        Comparison.EQ,
                        ExpressionGenerators.literal(9), castResolver())),
                select_HKeyOrdered(
                    groupScan_Default(uGroupTable),
                    uRowType,
                    ExpressionGenerators.compare(
                        ExpressionGenerators.field(uRowType, 1),
                        Comparison.EQ,
                        ExpressionGenerators.literal(9), castResolver())),
                tRowType,
                uRowType, 
                2,
                2,
                ascending (true, true),
                false);
        RowBase[] expected = new RowBase[]{
            row(tRowType, 1001L, 9L),
            row(uRowType, 1002L, 9L),
            row(tRowType, 1003L, 9L),
            row(tRowType, 1005L, 9L),
            row(tRowType, 1007L, 9L)
        };
        compareRows(expected, cursor(plan, queryContext, queryBindings));
    }
    
    private boolean[] ascending(boolean... ascending)
    {
        return ascending;
    }
    
}

@@ -1192,24 +1192,156 @@
   %22x int%22);%0A
+        v = createTable (%0A             %22schema%22, %22v%22,%0A             %22id int not null primary key%22,%0A             %22name varchar(32)%22);%0A
     %7D%0A%0A    @
@@ -1546,24 +1546,82 @@
 rTable(u));%0A
+        vRowType = schema.userTableRowType(userTable(v));%0A
         tGro
@@ -1672,16 +1672,48 @@
 oup(u);%0A
+        vGroupTable = group(v);%0A
         
@@ -2408,16 +2408,19 @@
 int t, u
+, v
 ;%0A    pr
@@ -2460,16 +2460,26 @@
 uRowType
+, vRowType
 ;%0A    pr
@@ -2514,16 +2514,29 @@
 oupTable
+, vGroupTable
 ;%0A    %0A 
@@ -5018,24 +5018,774 @@
 %0A    %7D%0A    %0A
+    @Test(expected = IllegalArgumentException.class)%0A    public void testAllRowTypeMismatch () %7B%0A        unionAll_Default (%0A                groupScan_Default(tGroupTable),%0A                tRowType,%0A                groupScan_Default(vGroupTable),%0A                vRowType,%0A                true);%0A    %7D%0A    %0A    @Test (expected = IllegalArgumentException.class)%0A    public void testDifferentInputTypes() %0A    %7B%0A        // Test different input types%0A        union_Ordered(groupScan_Default(tGroupTable),%0A                      groupScan_Default(vGroupTable),%0A                      tRowType,%0A                      vRowType,%0A                      2,%0A                      2,%0A                      ascending(true,true),%0A                      false);%0A    %7D%0A%0A
     private 

Add tests for mismatches on row types (same number, not compatible types).