com.tesora.dve.sql.util.JdbcConnectionResourceResponse.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.sql.util.JdbcConnectionResourceResponse.java

Source

package com.tesora.dve.sql.util;

/*
 * #%L
 * Tesora Inc.
 * Database Virtualization Engine
 * %%
 * Copyright (C) 2011 - 2014 Tesora Inc.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 * 
 * 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/>.
 * #L%
 */

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.ObjectUtils;

import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.resultset.ColumnMetadata;
import com.tesora.dve.resultset.ColumnSet;
import com.tesora.dve.resultset.ResultRow;

public class JdbcConnectionResourceResponse extends ResourceResponse {

    private ResultSet results;
    private Long updateCount;
    private long lastInsertId;

    public JdbcConnectionResourceResponse(ResultSet res, Long uc, long lastInsertId) {
        results = res;
        updateCount = uc;
        this.lastInsertId = lastInsertId;
    }

    @Override
    public long getNumRowsAffected() {
        return (this.updateCount != null) ? this.updateCount : 0;
    }

    @Override
    public void assertEqualResponse(String cntxt, ResourceResponse other) throws Throwable {
        if (results != null) {
            // result set, not much we can do
        } else if (other instanceof JdbcConnectionResourceResponse) {
            JdbcConnectionResourceResponse othResp = (JdbcConnectionResourceResponse) other;
            assertEquals(cntxt + " row count", updateCount, othResp.updateCount);
        } else if (other instanceof ProxyConnectionResourceResponse) {
            ProxyConnectionResourceResponse othResp = (ProxyConnectionResourceResponse) other;
            assertEquals(cntxt + " row count", updateCount, new Long(othResp.getNumRowsAffected()));
        } else if (other == null) {
            // if the other side is null - that's a problem
            fail("missing other response");
        } else {
            throw new Throwable("What kind of ResourceResponse is " + other.getClass().getName());
        }
    }

    @Override
    public List<ResultRow> getResults() throws Throwable {
        return convertNativeResults(results);
    }

    @Override
    public List<ColumnChecker> getColumnCheckers() throws Throwable {
        ResultSetMetaData rsmd = results.getMetaData();
        ArrayList<ColumnChecker> checkers = new ArrayList<ColumnChecker>();
        for (int i = 1; i <= rsmd.getColumnCount(); i++) {
            int dt = rsmd.getColumnType(i);
            if (dt == Types.BINARY || dt == Types.VARBINARY || dt == Types.LONGVARBINARY)
                checkers.add(BLOB_COLUMN);
            else if (dt == Types.TIMESTAMP)
                checkers.add(TIMESTAMP_COLUMN);
            else
                checkers.add(REGULAR_COLUMN);
        }
        return checkers;
    }

    @Override
    public long getLastInsertId() throws PEException {
        return lastInsertId;
    }

    private void assertEqualJdbcMetadata(String cntxt, JdbcConnectionResourceResponse other) throws Throwable {
        ResultSetMetaData expected = results.getMetaData();
        ResultSetMetaData actual = other.results.getMetaData();
        assertEquals(cntxt + " result set width", expected.getColumnCount(), actual.getColumnCount());
        int nCols = expected.getColumnCount();
        for (int i = 1; i <= nCols; i++) {
            for (int f = 0; f < mdfields.length; f++) {
                mdfields[f].assertSame(cntxt, i, expected, actual);
            }
        }
    }

    private void assertEqualProxyConnMetadata(String cntxt, ProxyConnectionResourceResponse pcrr) throws Throwable {
        ResultSetMetaData rsmd = results.getMetaData();
        ColumnSet sysColumns = pcrr.getColumns();
        assertEquals(cntxt + " mismatched column set width", rsmd.getColumnCount(),
                sysColumns.getColumnList().size());
        List<ColumnMetadata> sysCols = sysColumns.getColumnList();
        for (int i = 0; i < rsmd.getColumnCount(); i++) {
            ColumnMetadata sc = sysCols.get(i);
            String colcntxt = cntxt + " column " + sc.getAliasName();
            // still don't handle non column labels right
            assertEquals(colcntxt + " mismatched column name", rsmd.getColumnName(i + 1), sc.getName());
            assertEquals(colcntxt + " mismatched column label", rsmd.getColumnLabel(i + 1), sc.getAliasName());
            if (rsmd.getColumnType(i + 1) != sc.getDataType()) {
                // emit names - easier to read
                fail(colcntxt + " mismatched column type.  Expected " + rsmd.getColumnTypeName(i + 1) + " ("
                        + rsmd.getColumnType(i + 1) + ") but found " + sc.getTypeName() + " (" + sc.getDataType()
                        + ")");
            }
        }
    }

    @Override
    public void assertEqualMetadata(String cntxt, ResourceResponse other) throws Throwable {
        if (other instanceof JdbcConnectionResourceResponse) {
            // handle differently
            assertEqualJdbcMetadata(cntxt, (JdbcConnectionResourceResponse) other);
        } else {
            assertEqualProxyConnMetadata(cntxt, (ProxyConnectionResourceResponse) other);
        }
    }

    private List<ResultRow> convertNativeResults(ResultSet mrs) throws Throwable {
        ResultSetMetaData rsmd = mrs.getMetaData();
        ArrayList<ResultRow> converted = new ArrayList<ResultRow>();
        while (mrs.next()) {
            ResultRow rr = new ResultRow();
            for (int i = 0; i < rsmd.getColumnCount(); i++) {
                rr.addResultColumn(mrs.getObject(i + 1), mrs.wasNull());
            }
            converted.add(rr);
        }
        return converted;
    }

    private static abstract class CheckMetadata {

        private String tag;

        public CheckMetadata(String what) {
            tag = what;
        }

        public void assertSame(String cntxt, int i, ResultSetMetaData expected, ResultSetMetaData actual)
                throws Exception {
            Object eval = getValue(expected, i);
            Object aval = getValue(actual, i);
            if (!ObjectUtils.equals(eval, aval))
                fail(cntxt + ", column " + i + " " + tag + ".  Expected: '" + eval + "'; Actual '" + aval + "'");
        }

        public abstract Object getValue(ResultSetMetaData rsmd, int column) throws Exception;
    }

    private static CheckMetadata[] mdfields = new CheckMetadata[] {
            // catalog name won't work because the two connections use different dbs
            //      new CheckMetadata("catalog name") { public Object getValue(ResultSetMetaData rsmd, int column) throws Exception { return rsmd.getCatalogName(column); }},
            // why doesn't column class name work?
            // new CheckMetadata("column class name") { public Object getValue(ResultSetMetaData rsmd, int column) throws Exception { return rsmd.getColumnClassName(column); }},
            // In some cases we end up with a different length than native - for example when we redist select count(*) we end up with 43 instead of 21
            //    - because we convert count to sum
            // new CheckMetadata("column display size") { public Object getValue(ResultSetMetaData rsmd, int column) throws Exception { return rsmd.getColumnDisplaySize(column); }},
            new CheckMetadata("column label") {
                @Override
                public Object getValue(ResultSetMetaData rsmd, int column) throws Exception {
                    return rsmd.getColumnLabel(column);
                }
            }, new CheckMetadata("column name") {
                @Override
                public Object getValue(ResultSetMetaData rsmd, int column) throws Exception {
                    return rsmd.getColumnName(column);
                }
            }, new CheckMetadata("column type") {
                @Override
                public Object getValue(ResultSetMetaData rsmd, int column) throws Exception {
                    return rsmd.getColumnType(column);
                }
            },
            // new CheckMetadata("column type name") { public Object getValue(ResultSetMetaData rsmd, int column) throws Exception { return rsmd.getColumnTypeName(column); }},
            //new CheckMetadata("precision") { public Object getValue(ResultSetMetaData rsmd, int column) throws Exception { return rsmd.getPrecision(column); }},
            //new CheckMetadata("scale") { public Object getValue(ResultSetMetaData rsmd, int column) throws Exception { return rsmd.getScale(column); }},
    };

}