net.certifi.audittablegen.PostgresqlDMR.java Source code

Java tutorial

Introduction

Here is the source code for net.certifi.audittablegen.PostgresqlDMR.java

Source

/*    Copyright 2014 Certifi Inc.
 *
 *    This file is part of AuditTableGen.
 *
 *        AuditTableGen is free software: you can redistribute it and/or modify
 *        it under the terms of the GNU General Public License as published by
 *        the Free Software Foundation, either version 3 of the License, or
 *        (at your option) any later version.
 *
 *        AuditTableGen 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 General Public License for more details.
 *
 *        You should have received a copy of the GNU General Public License
 *        along with AuditTableGen.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.certifi.audittablegen;

import com.google.common.base.Throwables;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.dbcp.BasicDataSource;
import org.postgresql.ds.PGPoolingDataSource;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Glenn Sacks
 */
public class PostgresqlDMR extends GenericDMR {
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AuditTableGen.class);

    PostgresqlDMR(DataSource ds) throws SQLException {

        super(ds);

    }

    PostgresqlDMR(DataSource ds, String schema) throws SQLException {

        super(ds, schema);

    }

    /**
     * Generate a Postgresql DataSource from Properties 
     * @param props
     * @return BasicDataSource as DataSource
     */
    static DataSource getRunTimeDataSource(Properties props) {

        //BasicDataSource dataSource = new BasicDataSource();
        PGPoolingDataSource dataSource = new PGPoolingDataSource();
        //PGSimpleDataSource dataSource = new PGSimpleDataSource();
        int port;
        dataSource.setUser(props.getProperty("username"));
        dataSource.setPassword(props.getProperty("password"));
        //dataSource.setInitialConnections(2);
        //dataSource.setApplicationName("AuditTableGen");
        dataSource.setServerName(props.getProperty("server"));
        dataSource.setDatabaseName(props.getProperty("database"));
        if (props.containsKey("port")) {
            port = Integer.getInteger(props.getProperty("port", "5432"));
            dataSource.setPortNumber(port);
        }

        //dataSource.setDriverClassName("org.postgresql.Driver");
        //dataSource.setUsername(props.getProperty("username"));
        //dataSource.setPassword(props.getProperty("password"));
        //dataSource.setUrl(props.getProperty("url"));
        //dataSource.setMaxActive(10);
        //dataSource.setMaxIdle(5);
        //dataSource.setInitialSize(5);
        //dataSource.setValidationQuery("SELECT 1");

        return dataSource;
    }

    public void printDataSourceStats() {
        try {
            if (dataSource.isWrapperFor(BasicDataSource.class)) {
                BasicDataSource bds = dataSource.unwrap(BasicDataSource.class);
                System.out.println("NumActive: " + bds.getNumActive());
                System.out.println("NumIdle: " + bds.getNumIdle());

            } else {
                System.out.println("DataSource Stats not available");
            }
        } catch (SQLException ex) {
            logger.error("Error getting DataSource stats:" + ex.getMessage());
        }

    }

    /**
     * Get List of ColumnDef objects for all tables
     * in the targeted database/schema.  Postgres specific code replaces 
     * 'serial' date type with integer, because the column in the audit table
     * must be of type integer and not serial.  Since this data is interpreted
     * by ChangeSourceFactory, which should be database independent, the
     * translation needs to be in the DMR.
     * 
     * @param tableName
     * @return ArrayList of ColumnDef objects or an empty list if none are found.
     */
    @Override
    public List getColumns(String tableName) {

        //getDataTypes will initialize the map if it isn't already loaded
        Map<String, DataTypeDef> dtds = getDataTypes();

        List columns = new ArrayList<>();

        try {
            Connection conn = dataSource.getConnection();
            DatabaseMetaData dmd = conn.getMetaData();
            ResultSet rs = dmd.getColumns(null, verifiedSchema, tableName, null);

            //load all of the metadata in the result set into a map for each column

            ResultSetMetaData rsmd = rs.getMetaData();
            int metaDataColumnCount = rsmd.getColumnCount();
            if (!rs.isBeforeFirst()) {
                throw new RuntimeException(
                        "No results for DatabaseMetaData.getColumns(" + verifiedSchema + "." + tableName + ")");
            }
            while (rs.next()) {
                ColumnDef columnDef = new ColumnDef();
                Map columnMetaData = new CaseInsensitiveMap();
                for (int i = 1; i <= metaDataColumnCount; i++) {
                    columnMetaData.put(rsmd.getColumnName(i), rs.getString(i));
                }
                columnDef.setName(rs.getString("COLUMN_NAME"));

                String type_name = rs.getString("TYPE_NAME");
                if (type_name.equalsIgnoreCase("serial")) {
                    columnDef.setTypeName("int4");
                } else {
                    columnDef.setTypeName(type_name);
                }
                columnDef.setSqlType(rs.getInt("DATA_TYPE"));
                columnDef.setSize(rs.getInt("COLUMN_SIZE"));
                columnDef.setDecimalSize(rs.getInt("DECIMAL_DIGITS"));
                columnDef.setSourceMeta(columnMetaData);

                if (dtds.containsKey(columnDef.getTypeName())) {
                    columnDef.setDataTypeDef(dtds.get(columnDef.getTypeName()));
                } else {
                    throw new RuntimeException(
                            "Missing DATA_TYPE definition for data type " + columnDef.getTypeName());
                }
                columns.add(columnDef);
            }

        } catch (SQLException e) {
            throw Throwables.propagate(e);
        }

        return columns;

    }

}