Package com.foundationdb.sql.pg

Source Code of com.foundationdb.sql.pg.PostgresServerJDBCTypesITBase

/**
* 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.sql.pg;


import com.foundationdb.junit.SelectedParameterizedRunner;

import com.foundationdb.sql.jdbc.util.PSQLException;

import java.sql.*;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.UUID;

import com.foundationdb.sql.jdbc.util.PSQLState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized.Parameters;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
* Test using various JDBC <code>set</code> and <code>get</code> methods.
*/
@RunWith(SelectedParameterizedRunner.class)
public abstract class PostgresServerJDBCTypesITBase extends PostgresServerITBase
{

    @Before
    public void createTable() throws Exception {
        SimpleColumn columns[] = {
            new SimpleColumn("col_boolean", "AKSQL_ boolean"),
            new SimpleColumn("col_tinyint", "MCOMPAT_ tinyint"),
            new SimpleColumn("col_varbinary", "MCOMPAT_ varbinary", 256L, null),
            new SimpleColumn("col_date", "MCOMPAT_ date"),
            new SimpleColumn("col_decimal", "MCOMPAT_ decimal", 5L, 2L),
            new SimpleColumn("col_double", "MCOMPAT_ double"),
            new SimpleColumn("col_float", "MCOMPAT_ float"),
            new SimpleColumn("col_int", "MCOMPAT_ int"),
            new SimpleColumn("col_bigint", "MCOMPAT_ bigint"),
            new SimpleColumn("col_smallint", "MCOMPAT_ smallint"),
            new SimpleColumn("col_varchar", "MCOMPAT_ varchar", 16L, null),
            new SimpleColumn("col_time", "MCOMPAT_ time"),
            new SimpleColumn("col_datetime", "MCOMPAT_ datetime"),
            new SimpleColumn("col_guid", "AKSQL_ GUID"),
        };
        createTableFromTypes(SCHEMA_NAME, "types", false, false, columns);
    }

    @Before
    public void ensureCorrectConnectionType() throws Exception {
        forgetConnection();
    }

    @Override
    protected String getConnectionURL() {
        // loglevel=2 is also useful for seeing what's really happening.
        return super.getConnectionURL() + "?prepareThreshold=1&binaryTransfer=" + binaryTransfer();
    }

    protected abstract boolean binaryTransfer();

    /**
     * @param unparseable some sort of string that couldn't possibly be parsed (e.g. an int of value "Suzie")
     * @param defaultValue the default value that should come back if you pass in a wildly incorrect string
     */
    static Object[] tc(String name, int jdbcType, String colName, Object value,
                       String unparseable, Object defaultValue) {
        return new Object[] { name, jdbcType, colName, value, unparseable, defaultValue};
    }

    @Parameters(name="{0}")
    public static Iterable<Object[]> types() throws Exception {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.MILLISECOND, 0);
        long timeNoMillis = cal.getTime().getTime();
        Calendar dcal = (Calendar)cal.clone();
        dcal.set(Calendar.HOUR_OF_DAY, 0);
        dcal.set(Calendar.MINUTE, 0);
        dcal.set(Calendar.SECOND, 0);
        long startOfDay = dcal.getTime().getTime();
        Calendar tcal = (Calendar)cal.clone();
        tcal.set(Calendar.YEAR, 1970);
        tcal.set(Calendar.MONTH, 0);
        tcal.set(Calendar.DAY_OF_MONTH, 1);
        long timeOfDay = tcal.getTime().getTime();
        Object[][] tcs = new Object[][] {
            tc("BigDecimal", Types.DECIMAL, "col_decimal", new BigDecimal("3.14"), "Suzie", new BigDecimal("0.00")),
            tc("Boolean", Types.BOOLEAN, "col_boolean", Boolean.TRUE, "Jack", false),
            tc("Byte", Types.TINYINT, "col_tinyint", (byte)123, "Lewis", (byte)0),
            // strings are parsed into byte arrays
            tc("Bytes", Types.VARBINARY, "col_varbinary", new byte[] { 0, 1, (byte)0xFF }, null, null),
            tc("Date", Types.DATE, "col_date", new Date(startOfDay), "Janet", null),
            tc("Double", Types.DOUBLE, "col_double", 3.14E52, "Bridget", 0.0),
            tc("Float", Types.FLOAT, "col_float", 3.14f, "Willy", 0.0f),
            tc("Int", Types.INTEGER, "col_int", 123456, "Mary", 0),
            tc("Long", Types.BIGINT, "col_bigint", 0x12345678L, "Jimmy", 0L),
            tc("Short", Types.SMALLINT, "col_smallint", (short)1001, "Martha", (short)0),
            // obviously any string can be a string
            tc("String", Types.VARCHAR, "col_varchar", "hello", null, null),
            tc("Time", Types.TIME, "col_time", new Time(timeOfDay), "Mike", null),
            tc("Timestamp(Datetime)", Types.TIMESTAMP, "col_datetime", new Timestamp(timeNoMillis), "Bob", null),
            tc("GUID", Types.OTHER, "col_guid", UUID.randomUUID(), "3249",
               new PSQLException("3249", new PSQLState("2202I"))),
        };
        return Arrays.asList(tcs);
    }

    private final String caseName;
    private final int jdbcType;
    private final String colName;
    private final Object value;
    private final String unparseable;
    private final Object defaultValue;

    public PostgresServerJDBCTypesITBase(String caseName, int jdbcType, String colName,
                                         Object value, String unparseable, Object defaultValue) {
        this.caseName = caseName;
        this.jdbcType = jdbcType;
        this.colName = colName;
        this.value = value;
        this.unparseable = unparseable;
        this.defaultValue = defaultValue;
    }

    @Test
    public void setAndGet() throws Exception {
        PreparedStatement setStmt = getConnection().prepareStatement(String.format("INSERT INTO types(id,%s) VALUES(?,?)", colName));
        PreparedStatement getStmt = getConnection().prepareStatement(String.format("SELECT %s FROM types WHERE id = ?", colName));

        setStmt.setInt(1, 1);
        setStmt.setObject(2, value, jdbcType);
        setStmt.executeUpdate();
        getStmt.setInt(1, 1);
        ResultSet rs = getStmt.executeQuery();
        assertTrue(rs.next());
        compareObjects(asObject(value, jdbcType), rs.getObject(1));
        rs.close();
       
        setStmt.setInt(1, 2);
        setMethod(setStmt, 2, value, jdbcType);
        setStmt.executeUpdate();
        getStmt.setInt(1, 2);
        rs = getStmt.executeQuery();
        assertTrue(rs.next());
        compareObjects(value, getMethod(rs, 1, jdbcType));
        rs.close();
       
        getStmt.close();
        setStmt.close();
    }

    @Test
    public void setAsString() throws Exception {
        PreparedStatement setStmt = getConnection().prepareStatement(String.format("INSERT INTO types(id,%s) VALUES(?,?)", colName));
        PreparedStatement getStmt = getConnection().prepareStatement(String.format("SELECT %s FROM types WHERE id = ?", colName));
        Object valueForStrings = value;
        // "3true" -> true
        // check out Date with "3"+value.toString()
        // also Date/Time with value.toString() + "3" -> get's parsed as null
        // bytes need special handling here.
        if (value instanceof byte[]) {
            byte[] bytes = (byte[])value;
            byte[] bytesCopy = new byte[bytes.length];
            valueForStrings = bytesCopy;
            // large bytes fall over when you try to encode them as UTF-8
            // not going to worry about that here
            for (int i=0; i<bytes.length; i++) {
                if (bytes[i] < 0) {
                    bytesCopy[i] = 37;
                } else {
                    bytesCopy[i] = bytes[i];
                }
            }
            setStmt.setString(2, new String(bytesCopy, "UTF-8"));
        } else {
            setStmt.setString(2, valueForStrings.toString());
        }
        setStmt.setInt(1, 1);
        setStmt.executeUpdate();
        getStmt.setInt(1, 1);
        ResultSet rs = getStmt.executeQuery();
        assertTrue(rs.next());
        compareObjects(asObject(valueForStrings, jdbcType), rs.getObject(1));
        rs.close();

        getStmt.close();
        setStmt.close();
    }

    @Test
    public void setUnparseableString() throws Exception {
        PreparedStatement setStmt = getConnection().prepareStatement(String.format("INSERT INTO types(id,%s) VALUES(?,?)", colName));
        PreparedStatement getStmt = getConnection().prepareStatement(String.format("SELECT %s FROM types WHERE id = ?", colName));
        setStmt.setString(2, unparseable);
        setStmt.setInt(1, 1);
        if (defaultValue instanceof Exception) {
            try {
                setStmt.executeUpdate();
                fail("Expected an exception to be thrown");
            } catch (Exception e) {
                assertThat(e, is(instanceOf(defaultValue.getClass())));
                assertThat(e.getMessage(), containsString(((Exception) defaultValue).getMessage()));
                if (defaultValue instanceof PSQLException) {
                    assertEquals(((PSQLException)defaultValue).getSQLState(),
                            ((PSQLException)e).getSQLState());
                }
            }
        } else {
            setStmt.executeUpdate();
            getStmt.setInt(1, 1);
            ResultSet rs = getStmt.executeQuery();
            assertTrue(rs.next());
            compareObjects(asObject(defaultValue, jdbcType), rs.getObject(1));
            rs.close();

            getStmt.close();
        }
        setStmt.close();
    }

    protected static void setMethod(PreparedStatement stmt, int index,
                                    Object value, int jdbcType)
            throws Exception {
        switch (jdbcType) {
        case Types.DECIMAL:
            stmt.setBigDecimal(index, (BigDecimal)value);
            break;
        case Types.BOOLEAN:
            stmt.setBoolean(index, (Boolean)value);
            break;
        case Types.TINYINT:
            stmt.setByte(index, (Byte)value);
            break;
        case Types.VARBINARY:
            stmt.setBytes(index, (byte[])value);
            break;
        case Types.DATE:
            stmt.setDate(index, (Date)value);
            break;
        case Types.DOUBLE:
            stmt.setDouble(index, (Double)value);
            break;
        case Types.FLOAT:
            stmt.setFloat(index, (Float)value);
            break;
        case Types.INTEGER:
            stmt.setInt(index, (Integer)value);
            break;
        case Types.BIGINT:
            stmt.setLong(index, (Long)value);
            break;
        case Types.SMALLINT:
            stmt.setShort(index, (Short)value);
            break;
        case Types.VARCHAR:
            stmt.setString(index, (String)value);
            break;
        case Types.TIME:
            stmt.setTime(index, (Time)value);
            break;
        case Types.TIMESTAMP:
            stmt.setTimestamp(index, (Timestamp)value);
            break;
        case Types.OTHER:
            stmt.setObject(index, value);
            break;
        default:
            fail("Unknown JDBC type");
        }
    }

    protected static Object getMethod(ResultSet rs, int index, int jdbcType)
            throws Exception {
        switch (jdbcType) {
        case Types.DECIMAL:
            return rs.getBigDecimal(index);
        case Types.BOOLEAN:
            return rs.getBoolean(index);
        case Types.TINYINT:
            return rs.getByte(index);
        case Types.VARBINARY:
            return rs.getBytes(index);
        case Types.DATE:
            return rs.getDate(index);
        case Types.DOUBLE:
            return rs.getDouble(index);
        case Types.FLOAT:
            return rs.getFloat(index);
        case Types.INTEGER:
            return rs.getInt(index);
        case Types.BIGINT:
            return rs.getLong(index);
        case Types.SMALLINT:
            return rs.getShort(index);
        case Types.VARCHAR:
            return rs.getString(index);
        case Types.TIME:
            return rs.getTime(index);
        case Types.TIMESTAMP:
            return rs.getTimestamp(index);
        case Types.OTHER:
            return rs.getObject(index);
        default:
            fail("Unknown JDBC type");
            return null;
        }
    }

    protected static Object asObject(Object value, int jdbcType) {
        switch (jdbcType) {
        case Types.TINYINT:
            return ((Byte)value).intValue();
        case Types.SMALLINT:
            return ((Short)value).intValue();
        default:
            return value;
        }
    }

    protected static void compareObjects(Object expected, Object actual) {
        if (expected instanceof byte[]) {
            assertArrayEquals((byte[]) expected, (byte[]) actual);
        }
        else if (expected instanceof java.util.Date) {
            assertEquals(String.format("%s <> %s",
                                       ((java.util.Date)expected).getTime(),
                                       ((java.util.Date)actual).getTime()),
                         expected, actual);
        }
        else {
            assertEquals(expected, actual);
        }
    }

}
TOP

Related Classes of com.foundationdb.sql.pg.PostgresServerJDBCTypesITBase

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.