All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.intermine.sql.logging.DatabaseWriter Maven / Gradle / Ivy

package org.intermine.sql.logging;

/*
 * Copyright (C) 2002-2022 FlyMine
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  See the LICENSE file for more
 * information or http://www.gnu.org/copyleft/lesser.html.
 *
 */

import java.io.IOException;
import java.io.Writer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.intermine.metadata.StringUtil;

/**
 * Writes tab-separated Strings to a database table
 *
 * @author Andrew Varley
 */
public class DatabaseWriter extends Writer
{
    protected Connection con;
    protected String table;
    protected StringBuffer sb = new StringBuffer();
    protected int fields = 0;

    /**
     * Construct an empty DatabaseWriter for testing purposes
     *
     */
    public DatabaseWriter() {
    }

   /**
     * Construct a DatabaseWriter
     *
     * @param con a database Connection
     * @param table the table to write to
     * @throws NullPointerException if either con or table are null
     */
    public DatabaseWriter(Connection con, String table) {
        if (con == null) {
            throw new NullPointerException("Connection cannot be null");
        }
        if (table == null) {
            throw new NullPointerException("Database table cannot be null");
        }
        this.con = con;
        this.table = table;
    }

    /**
     * Write a portion of an array to the database
     *
     * @param cbuff the array of characters
     * @param off the start point
     * @param len the number of characters to write
     * @throws IOException if an error occurs when writing to the underlying database
     */
    @Override
    public void write(char[] cbuff, int off, int len) throws IOException {
        if (cbuff == null) {
            return;
        }
        sb.append(cbuff, off, len);

        List rows = new ArrayList();
        int index = -1;

        while ((index = sb.indexOf(System.getProperty("line.separator"))) != -1) {
            rows.add(sb.substring(0, index));
            if (index < sb.length()) {
                sb = new StringBuffer(sb.substring(index + 1));
            }
        }
        writeRows(rows);
    }

    /**
     * Flush completed rows to the database
     */
    @Override
    public void flush() {
    }

    /**
     * Close this Writer
     */
    @Override
    public void close() {
    }


    /**
     * Creates an SQL String suitable for initialising a PreparedStatement
     *
     * @param table the table to insert in
     * @param row an example row
     * @return the SQL String
     * @throws NullPointerException if any arguments are null
     */
    protected String createSQLStatement(String table, String row) {
        if ((table == null) || (row == null)) {
            throw new NullPointerException("Arguments to createSQLStatement must not be null");
        }

        fields = StringUtil.countOccurances("\t", row) + 1;

        StringBuffer sql = new StringBuffer();

        sql.append("INSERT INTO ")
            .append(table)
            .append(" VALUES(");
        for (int i = 0; i < fields; i++) {
            sql.append("?");
            if (i != (fields - 1)) {
                sql.append(", ");
            }
        }
        sql.append(")");

        return sql.toString();
    }

    /**
     * Actually do the writing of the rows to the database
     *
     * @param rows a List of rows to write
     * @throws IOException if an error occurs within the database
     */
    private void writeRows(List rows) throws IOException {
        boolean autoCommit = false;
        PreparedStatement pstmt;

        if (rows.size() == 0) {
            return;
        }

        try {
            autoCommit = con.getAutoCommit();
            pstmt = con.prepareStatement(createSQLStatement(table, rows.get(0)));

            for (String row : rows) {
                StringTokenizer st = new StringTokenizer(row, "\t", false);
                int j = 1;
                while (st.hasMoreTokens()) {
                    pstmt.setString(j++, st.nextToken().trim());
                }
                if (j <= fields) {
                    throw new IOException("Too few fields");
                }

                pstmt.addBatch();
            }

            pstmt.executeBatch();
            con.commit();
        } catch (SQLException e) {
            throw new IOException(e.getMessage());
        } finally {
            try {
                con.setAutoCommit(autoCommit);
            } catch (SQLException e) {
                // Do nothing
            }
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy