Package org.voltdb

Source Code of org.voltdb.TestVoltTable

/* This file is part of VoltDB.
* Copyright (C) 2008-2010 VoltDB L.L.C.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

package org.voltdb;

import java.math.BigDecimal;
import java.util.Arrays;

import junit.framework.TestCase;

import org.voltdb.VoltTable.ColumnInfo;
import org.voltdb.messaging.FastSerializableTestUtil;
import org.voltdb.types.TimestampType;
import org.voltdb.types.VoltDecimalHelper;

public class TestVoltTable extends TestCase {
    private VoltTable LONG_FIVE;
    private VoltTable t;
    private VoltTable t2;
    @Override
    public void setUp() {
        LONG_FIVE = new VoltTable(new VoltTable.ColumnInfo("Test", VoltType.BIGINT));
        LONG_FIVE.addRow(5L);
        t = new VoltTable();
        t2 = new VoltTable();
    }

    void addAllPrimitives(Class<?>[] permittedTypes) {
        Object[] primitives = {
            null,
            (byte) 0,
            (short) 1,
            (short) 2,
            3,
            4L,
            5.01f,
            6.02,
            "string",
            new byte[] { 'b', 'y', 't', 'e', 's' },
            new TimestampType(99),
            new BigDecimal(7654321).setScale(VoltDecimalHelper.kDefaultScale),
            new Object(),
        };

        for (Object o : primitives) {
            try {
                t.addRow(o);
                if (o != null && !contains(permittedTypes, o.getClass())) {
                    fail(o.getClass() + " is not permitted but addRow succeeded");
                }
            } catch (VoltTypeException e) {
                if (contains(permittedTypes, o.getClass())) {
                    fail(o.getClass() + " is permitted by addRow failed");
                }
            }
        }
    }

    // VoltTable initially sizes itself to fit exactly, so 2 longs should be sufficient to get
    // resizing. Use 16 to be on the safe side.
    private static final int LONGS_TO_RESIZE = 16;

    // return an VoltTable that needed to grow once.
    private VoltTable makeResizedTable() {
        VoltTable temp = new VoltTable(new ColumnInfo("Foo", VoltType.BIGINT));
        for (int i = 0; i < LONGS_TO_RESIZE; ++i) {
            temp.addRow((long) i);
        }
        return temp;
    }

    private static boolean contains(Class<?>[] types, Class<?> type) {
        for (Class<?> c : types) {
            if (type == c) return true;
        }
        return false;
    }

    private boolean comparisonHelper(Object lhs, Object rhs, VoltType vt) {
        switch (vt) {
        case TINYINT:
            Byte b1 = (Byte)lhs;
            Byte b2 = (Byte)rhs;
            return b1.byteValue() == b2.byteValue();
        case SMALLINT:
            Short s1 = (Short)lhs;
            Short s2 = (Short)rhs;
            return s1.shortValue() == s2.shortValue();
        case INTEGER:
            Integer i1 = (Integer)lhs;
            Integer i2 = (Integer)rhs;
            return i1.intValue() == i2.intValue();
        case BIGINT:
            Long l1 = (Long)lhs;
            Long l2 = (Long)rhs;
            return l1.longValue() == l2.longValue();
        case FLOAT:
            Double d1 = (Double)lhs;
            Double d2 = (Double)rhs;
            return (d1.compareTo(d2) == 0);
        case STRING:
            if (lhs == null && rhs == null) return true;
            if (lhs == VoltType.NULL_STRING && rhs == null) return true;
            return ((String)lhs).equals(rhs);
        case TIMESTAMP:
            if (lhs == null && rhs == null) return true;
            if (lhs == VoltType.NULL_TIMESTAMP && rhs == null) return true;
            return ((TimestampType)lhs).equals(rhs);
        case DECIMAL:
            if (lhs == null && rhs == null) return true;
            if (lhs == VoltType.NULL_DECIMAL && rhs == null) return true;
            if (lhs == null || rhs == null) return false;
            return ((BigDecimal)lhs).equals(rhs);
        }

        return false;
    }

    public void testMakeFromScalar() {
        assertEquals(1, LONG_FIVE.getColumnCount());
        assertEquals(1, LONG_FIVE.getRowCount());
        assertEquals("Test", LONG_FIVE.getColumnName(0));
    }

    public void testAsScalarLong() {
        assertEquals(5L, LONG_FIVE.asScalarLong());
    }

    public void testAddColumnNullName() {
        try {
            t = new VoltTable(new ColumnInfo(null, VoltType.BIGINT));
            fail("expected exception");
        } catch (IllegalArgumentException e) {}
    }

    public void testLongSchemaOver1K() {
        // this test would crash before r531
        StringBuilder columnname = new StringBuilder();
        while (columnname.length() < 8192) {
            columnname.append("ryanlikestheyankees");
        }
        t = new VoltTable(new ColumnInfo(columnname.toString(), VoltType.BIGINT));
        assertTrue(t.getColumnName(0).compareTo(columnname.toString()) == 0);
    }

    public void testColumnIndexBounds() {
        try {
            LONG_FIVE.fetchRow(0).getLong(-1);
            fail("expected exception");
        } catch (IndexOutOfBoundsException e) {}

        try {
            LONG_FIVE.fetchRow(0).getLong(1);
            fail("expected exception");
        } catch (IndexOutOfBoundsException e) {}
    }

    public void testColumnTypeMismatch() {
        try {
            LONG_FIVE.fetchRow(0).getString(0);
            fail("expected exception");
        } catch (IllegalArgumentException e) {}
    }

    public void testColumnByName() {
        t = new VoltTable(new ColumnInfo("foo", VoltType.STRING), new ColumnInfo("twofoo", VoltType.INTEGER));
        t.addRow("bar", 5);

        assertEquals(0, t.getColumnIndex("foo"));
        assertEquals(1, t.getColumnIndex("twofoo"));
        assertEquals(t.getColumnName(0).equals("foo"), true);
        assertEquals(t.getColumnName(1).equals("twofoo"), true);
        assertEquals(t.getColumnName(1).compareTo("twofoo"), 0);
        System.out.println(t.toString());

        VoltTableRow r = t.fetchRow(0);
        assertEquals("bar", r.getString("foo"));

        try {
            t.getColumnIndex("bar");
            fail("expected exception");
        } catch (IllegalArgumentException e) {}

        try {
            r.getString("bar");
            fail("expected exception");
        } catch (IllegalArgumentException e) {}
    }

    public void testAddRow() {
        t = new VoltTable(new ColumnInfo("foo", VoltType.BIGINT));
        try {
            t.addRow(42L, 47L);
            fail("expected exception (1)");
        } catch (IllegalArgumentException e) {}
        try {
            Object[] objs = new Object[] {new Long(50), new Long(51) };
            t.addRow(objs);
            fail("expected exception (2)");
        } catch (IllegalArgumentException e) {}
    }

    public void testResizedTable() {
        // Create a table big enough to require resizing
        t = makeResizedTable();

        assertEquals(LONGS_TO_RESIZE, t.getRowCount());
        for (int i = 0; i < LONGS_TO_RESIZE; ++i) {
            assertEquals(i, t.fetchRow(i).getLong(0));
        }
    }

    @SuppressWarnings("deprecation")
    public void testEquals() {
        assertFalse(LONG_FIVE.equals(null));
        assertFalse(LONG_FIVE.equals(new Object()));

        // Different column name
        t = new VoltTable(new VoltTable.ColumnInfo("Test2", VoltType.BIGINT));
        t.addRow(5L);
        assertFalse(LONG_FIVE.equals(t));

        // Different number of columns
        t = new VoltTable(
                new ColumnInfo("Test", VoltType.BIGINT),
                new ColumnInfo("Test2", VoltType.BIGINT)
        );
        assertFalse(LONG_FIVE.equals(t));
        t.addRow(5L, 10L);
        assertFalse(LONG_FIVE.equals(t));

        // These are the same table
        t = new VoltTable(
                new ColumnInfo("Test", VoltType.BIGINT)
        );
        t.addRow(5L);
        assertEquals(LONG_FIVE, t);

        // Test two tables with strings
        t = new VoltTable(new VoltTable.ColumnInfo("Foo", VoltType.STRING));
        t.addRow("Bar");
        VoltTable t2 = new VoltTable(new VoltTable.ColumnInfo("Foo", VoltType.STRING));
        t2.addRow("Baz");
        assertFalse(t.equals(t2));
        t2 = new VoltTable(new VoltTable.ColumnInfo("Foo", VoltType.STRING));
        t2.addRow("Bar");
        assertEquals(t, t2);
    }

    @SuppressWarnings("deprecation")
    public void testEqualsDeserialized() {
        t = makeResizedTable();
        t2 = FastSerializableTestUtil.roundTrip(t);
        boolean equal = t.equals(t2);
        assertTrue(equal);
    }

    public void testStrings() {
        t = new VoltTable(new ColumnInfo("", VoltType.STRING));
        addAllPrimitives(new Class[]{ String.class, byte[].class });
        t.addRow("");
        assertEquals("string", t.fetchRow(1).getString(0));

        t2 = FastSerializableTestUtil.roundTrip(t);
        assertEquals("", t2.getColumnName(0));
        assertEquals(4, t2.getRowCount());
        VoltTableRow r = t2.fetchRow(0);
        assertNull(r.getString(0));
        assertTrue(r.wasNull());

        assertEquals("string", t2.fetchRow(1).getString(0));
        assertEquals("bytes", t2.fetchRow(2).getString(0));
        assertEquals("", t2.fetchRow(3).getString(0));

        t2.clearRowData();
        assertTrue(t2.getRowCount() == 0);
    }

    public void testStringsAsBytes() {
        t = new VoltTable(new ColumnInfo("", VoltType.STRING));
        t.addRow(new byte[0]);
        final byte[] FOO = new byte[]{'f', 'o', 'o'};
        t.addRow(FOO);

        t2 = FastSerializableTestUtil.roundTrip(t);
        assertEquals(2, t2.getRowCount());
        assertEquals("", t2.fetchRow(0).getString(0));
        assertEquals(0, t2.fetchRow(0).getStringAsBytes(0).length);
        assertTrue(Arrays.equals(FOO, t2.fetchRow(1).getStringAsBytes(0)));
        assertEquals("foo", t2.fetchRow(1).getString(0));

        t2.clearRowData();
        assertTrue(t2.getRowCount() == 0);
    }

    public void testIntegers() {
        t = new VoltTable(new ColumnInfo("foo", VoltType.BIGINT));
        addAllPrimitives(new Class[] { Long.class, Integer.class, Short.class, Byte.class, Double.class, Float.class } );

        t2 = FastSerializableTestUtil.roundTrip(t);
        assertEquals(8, t2.getRowCount());
        assertEquals(0, t2.fetchRow(1).getLong(0));

        VoltTableRow r = t2.fetchRow(0);
        assertEquals(VoltType.NULL_BIGINT, r.getLong(0));
        assertTrue(r.wasNull());

        t2.clearRowData();
        assertTrue(t2.getRowCount() == 0);
    }

    public void testExactTypes() {
        VoltTable basecase = new VoltTable(new ColumnInfo("foo", VoltType.DECIMAL));
        basecase.addRow(new BigDecimal(7654321).setScale(VoltDecimalHelper.kDefaultScale));
        VoltTableRow basecaserow = basecase.fetchRow(0);
        BigDecimal bd = basecaserow.getDecimalAsBigDecimal(0);
        assertEquals(bd, new BigDecimal(7654321).setScale(VoltDecimalHelper.kDefaultScale));

        t = new VoltTable(new ColumnInfo("foo", VoltType.DECIMAL));
        addAllPrimitives(new Class[] { BigDecimal.class });

        t2 = FastSerializableTestUtil.roundTrip(t);
        assertEquals(2, t2.getRowCount());

        // row 0 contains NULL
        VoltTableRow r = t2.fetchRow(0);
        r.getDecimalAsBigDecimal(0);
        assertTrue(r.wasNull());

        // row 1 contains a known value
        r = t2.fetchRow(1);
        assertTrue(new BigDecimal(7654321).setScale(VoltDecimalHelper.kDefaultScale).
                   equals(r.getDecimalAsBigDecimal(0)));

        t2.clearRowData();
        assertTrue(t2.getRowCount() == 0);
    }

    public void testFloats() {
        t = new VoltTable(new ColumnInfo("foo", VoltType.FLOAT));
        addAllPrimitives(new Class[]{ Long.class, Integer.class, Short.class,
                                      Byte.class, Double.class, Float.class });

        t2 = FastSerializableTestUtil.roundTrip(t);
        assertEquals(8, t2.getRowCount());
        VoltTableRow r = t2.fetchRow(0);
        assertEquals(VoltType.NULL_FLOAT, r.getDouble(0));
        assertTrue(r.wasNull());

        assertEquals(0.0, t2.fetchRow(1).getDouble(0), .000001);
        assertEquals(1.0, t2.fetchRow(2).getDouble(0), .000001);
        assertEquals(2.0, t2.fetchRow(3).getDouble(0), .000001);
        assertEquals(3.0, t2.fetchRow(4).getDouble(0), .000001);
        assertEquals(4.0, t2.fetchRow(5).getDouble(0), .000001);
        assertEquals(5.01, t2.fetchRow(6).getDouble(0), .000001);
        assertEquals(6.02, t2.fetchRow(7).getDouble(0), .000001);

        t2.clearRowData();
        assertTrue(t2.getRowCount() == 0);
    }

    // At least check that NULL_VALUEs of one type get interpreted as NULL
    // if we attempt to put them into a column of a different type
    public void testNulls()
    {
        VoltType[] types =
        {VoltType.TINYINT, VoltType.SMALLINT, VoltType.INTEGER,
         VoltType.BIGINT, VoltType.FLOAT, VoltType.DECIMAL,
         VoltType.TIMESTAMP, VoltType.STRING};

        for (int i = 0; i < types.length; ++i)
        {
            for (int j = 0; j < types.length; ++j)
            {
                VoltTable table =
                    new VoltTable(new ColumnInfo("test_table", types[i]));
                table.addRow(types[j].getNullValue());
                VoltTableRow row = table.fetchRow(0);
                row.get(0, types[i]);
                assertTrue("Value wasn't null", row.wasNull());
            }
        }
    }

    public void testTruncatingCasts()
    {
        VoltType[] test_types =
        {VoltType.TINYINT, VoltType.SMALLINT, VoltType.INTEGER};

        Object[][] test_vals =
        {{(long) Byte.MAX_VALUE, ((long) Byte.MAX_VALUE) + 1,
            ((long) Byte.MIN_VALUE) - 1},
         {(long) Short.MAX_VALUE, ((long) Short.MAX_VALUE) + 1,
                ((long) Short.MIN_VALUE) - 1},
         {(long) Integer.MAX_VALUE, ((long) Integer.MAX_VALUE) + 1,
                    ((long) Integer.MIN_VALUE) - 1}};

        for (int i = 0; i < test_types.length; ++i)
        {
            t = new VoltTable(new ColumnInfo("test_table", test_types[i]));
            t.addRow(test_vals[i][0]);
            boolean caught = false;
            try
            {
                t.addRow(test_vals[i][1]);
            }
            catch (VoltTypeException e)
            {
                caught = true;
            }
            assertTrue("Failed on: " + test_types[i].toString(), caught);

            caught = false;
            try
            {
                t.addRow(test_vals[i][2]);
            }
            catch (VoltTypeException e)
            {
                caught = true;
            }
            assertTrue("Failed on: " + test_types[i].toString(), caught);
        }
    }

    public void testTimestamps() {
        t = new VoltTable(new ColumnInfo("foo", VoltType.TIMESTAMP));
        addAllPrimitives(new Class[]{Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, TimestampType.class});

        t2 = FastSerializableTestUtil.roundTrip(t);
        assertEquals(9, t2.getRowCount());
        assertEquals(0L, t2.fetchRow(1).getTimestampAsTimestamp(0).getTime());
        assertEquals(0L, t2.fetchRow(1).getTimestampAsLong(0));
        assertEquals(1L, t2.fetchRow(2).getTimestampAsTimestamp(0).getTime());
        assertEquals(1L, t2.fetchRow(2).getTimestampAsLong(0));

        VoltTableRow r = t2.fetchRow(0);
        assertNull(r.getTimestampAsTimestamp(0));
        assertTrue(r.wasNull());

        r = t2.fetchRow(0);
        assertEquals(VoltType.NULL_BIGINT, r.getTimestampAsLong(0));
        assertTrue(r.wasNull());

        t2.clearRowData();
        assertTrue(t2.getRowCount() == 0);
    }

    public void testAddRowExceptionSafe() {
        t = new VoltTable(
                new ColumnInfo("foo", VoltType.BIGINT),
                new ColumnInfo("bar", VoltType.STRING),
                new ColumnInfo("baz", VoltType.BIGINT)
        );

        t.addRow(0L, "a", 1L);
        try {
            t.addRow(42L,"", "bad");
            fail("expected exception");
        } catch (VoltTypeException e) {}
        t.addRow(2L, "b", 3L);

        // the contents of the table should not be corrupted
        assertEquals(2, t.getRowCount());
        assertEquals(0L, t.fetchRow(0).getLong(0));
        assertEquals("a", t.fetchRow(0).getString(1));
        assertEquals(1L, t.fetchRow(0).getLong(2));
        assertEquals(2L, t.fetchRow(1).getLong(0));
        assertEquals("b", t.fetchRow(1).getString(1));
        assertEquals(3L, t.fetchRow(1).getLong(2));
    }

    public void testClone() {
        VoltTable item_data_template = new VoltTable(
                new ColumnInfo("i_name", VoltType.STRING),
                new ColumnInfo("s_quantity", VoltType.BIGINT),
                new ColumnInfo("brand_generic", VoltType.STRING),
                new ColumnInfo("i_price", VoltType.FLOAT),
                new ColumnInfo("ol_amount", VoltType.FLOAT)
        );
        VoltTable item_data = item_data_template.clone(1024);
        assertEquals(5, item_data.getColumnCount());
        assertEquals("i_name", item_data.getColumnName(0));
        assertEquals("s_quantity", item_data.getColumnName(1));
        assertEquals("brand_generic", item_data.getColumnName(2));
        assertEquals("i_price", item_data.getColumnName(3));
        assertEquals("ol_amount", item_data.getColumnName(4));
        assertEquals(VoltType.STRING, item_data.getColumnType(0));
        assertEquals(VoltType.BIGINT, item_data.getColumnType(1));
        assertEquals(VoltType.STRING, item_data.getColumnType(2));
        assertEquals(VoltType.FLOAT, item_data.getColumnType(3));
        assertEquals(VoltType.FLOAT, item_data.getColumnType(4));
        item_data.addRow("asdfsdgfsdg", 123L, "a", 45.0d, 656.2d);
    }

    public void testRowIterator() {

        // Test iteration of empty table
        VoltTable empty = new VoltTable();

        // make sure it craps out
        try {
            empty.getLong(1);
            fail();
        }
        catch(Exception e) {};

        assertEquals(-1, empty.getActiveRowIndex());
        assertFalse(empty.advanceRow());

        // Make a table with info to iterate

        t = new VoltTable(new ColumnInfo("foo", VoltType.BIGINT), new ColumnInfo("bar", VoltType.STRING));
        for (int i = 0; i < 10; i++) {
            t.addRow(i, String.valueOf(i));
        }

        int rowcount = 0;
        VoltTableRow copy = null;
        while (t.advanceRow()) {
            assertEquals(rowcount, t.getLong(0));
            assertTrue(String.valueOf(rowcount).equals(t.getString(1)));
            if (rowcount == 4) copy = t.cloneRow();
            rowcount++;
        }
        assertEquals(10, rowcount);

        rowcount = 5;
        while (copy.advanceRow()) {
            assertEquals(rowcount, copy.getLong(0));
            assertTrue(String.valueOf(rowcount).equals(copy.getString(1)));
            rowcount++;
        }
        assertEquals(10, rowcount);
    }

    public void testStupidAdvanceRowUse() {
        VoltTable table = new VoltTable(new ColumnInfo("foo", VoltType.BIGINT));
        table.addRow(5);
        // try to access value without calling advanceRow
        try {
            table.getLong(0);
            fail();
        }
        catch (RuntimeException e) {
            assertTrue(e.getMessage().startsWith("VoltTableRow.advanceRow"));
        }
    }

    public void testRowGet() {

        byte       b1 = (byte)1;
        short      s1 = (short)2;
        int        i1 = 3;
        long       l1 = Long.MIN_VALUE + 1;
        double     f1 = 3.5;
        String     S1 = "A";
        TimestampType d1  = new TimestampType(0);
        BigDecimal B1 = new BigDecimal(7654321).setScale(VoltDecimalHelper.kDefaultScale);

        // create a table with one column per supported type with NULLS on the left to right diagonal.
        // tinyint is intentionally first AND last to test that wasNull is correctly cleared by the
        // the next-to-last instance and re-initialized by tinyint.

        Object content[] = { b1, S1, i1, l1, f1, s1, d1, B1, b1 };

        Object nulls[] = { VoltType.NULL_TINYINT, VoltType.NULL_STRING, VoltType.NULL_INTEGER,
                           VoltType.NULL_BIGINT, VoltType.NULL_FLOAT, VoltType.NULL_SMALLINT,
                           VoltType.NULL_TIMESTAMP, VoltType.NULL_DECIMAL, VoltType.NULL_TINYINT };

        VoltType types[] = { VoltType.TINYINT, VoltType.STRING, VoltType.INTEGER,
                           VoltType.BIGINT, VoltType.FLOAT, VoltType.SMALLINT, VoltType.TIMESTAMP,
                           VoltType.DECIMAL, VoltType.TINYINT };

        VoltTable tt = new VoltTable(
            new ColumnInfo("tinyint",   types[0]),
            new ColumnInfo("string",    types[1]),
            new ColumnInfo("integer",   types[2]),
            new ColumnInfo("bigint",    types[3]),
            new ColumnInfo("float",     types[4]),
            new ColumnInfo("smallint",  types[5]),
            new ColumnInfo("timestamp", types[6]),
            new ColumnInfo("decimal",   types[7]),
            new ColumnInfo("tinyint",   types[0]));

        for (int i=0; i < content.length; ++i) {
            Object[] vals = new Object[content.length];;
            for (int k=0; k < content.length; k++) {
                if (i == k)
                    vals[k] = nulls[k];
                else
                    vals[k] = content[k];
            }
            System.out.println("Adding row: " + i);
            tt.addRow(vals);
        }

        // now iterate all the fields in the table and verify that row.get(idx, type)
        // works and that the wasNull state is correctly set and cleared.
        System.out.println(tt);
        int rowcounter = 0;
        while (tt.advanceRow()) {
            for (int k =0; k < content.length; k++) {
                System.out.println("verifying row:" + rowcounter + " col:" + k);

                if (rowcounter == k) {
                    boolean result = comparisonHelper(nulls[k], tt.get(k, types[k]), types[k]);
                    assertTrue(result);
                    assertTrue(tt.wasNull());
                }
                else {
                    Object got =  tt.get(k, types[k]);
                    System.out.println("Type: " + types[k]);
                    System.out.println("Expecting: " + content[k]);
                    System.out.println("Got: " + got);
                    assertTrue(comparisonHelper(content[k], got, types[k]));
                    assertFalse(tt.wasNull());
                }
            }
            rowcounter++;
        }
        assertEquals(rowcounter, content.length);
    }
}
TOP

Related Classes of org.voltdb.TestVoltTable

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.