Commit 1f42c1a6 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Improvements in SQL TAP Schema Update (implemented using transaction)

parent 5ef04b5d
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ public class SchemaDL {
                        Key key = keys.get(constraintName);
                        if (key == null) {
                            String keyId = "" + keys.size() + 1;
                            key = new Key(keyId, fromTable, targetTable);
                            key = new Key(fromTable, targetTable);
                            keys.put(constraintName, key);
                            keysMap.put(keyId, key);
                        }
@@ -63,7 +63,7 @@ public class SchemaDL {

    public static Table loadTable(final Connection connection, final String tapSchemaName, final Schema schema, final String tableName) throws SQLException {
        Table table = new Table(connection, tapSchemaName, schema, tableName, true);
        for (IDbEntity column : table.getAllEntities()) {
        for (DbEntity column : table.getAllEntities()) {
            // Select all table columns by default
            column.setStatus(Status.SELECTED_TO_SAVE);
        }
@@ -85,6 +85,10 @@ public class SchemaDL {
                        }

                        Table table = new Table(connection, tapSchemaName, schema, tableName, toCreate);
                        
                        table.setValue(Table.UTYPE, resultSet.getString("utype"));
                        table.setValue(Table.DESCRIPTION, resultSet.getString("description"));
                        
                        table.setStatus(Status.SELECTED_SAVED);
                        schema.addEntity(tableName, table);
                    }
+6 −6
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ public class TableDL {
            public void manipulateItem(ResultSet resultSet) throws SQLException {

                Column column = new Column();
                column.setTableName(table.getName());
                column.setTableName(table.getFullName());
                column.setStatus(Status.NOT_SELECTED);

                // Key
@@ -100,10 +100,10 @@ public class TableDL {

                        // updates variables of current column structure
                        column.setTableName(columnsResultSet.getString("table_name"));
                        column.setUtype(columnsResultSet.getString("utype"));
                        column.setUcd(columnsResultSet.getString("ucd"));
                        column.setUnit(columnsResultSet.getString("unit"));
                        column.setDescription(columnsResultSet.getString("description"));
                        column.setValue(Column.UTYPE, columnsResultSet.getString("utype"));
                        column.setValue(Column.UCD, columnsResultSet.getString("ucd"));
                        column.setValue(Column.UNIT, columnsResultSet.getString("unit"));
                        column.setValue(Column.DESCRIPTION, columnsResultSet.getString("description"));
                        column.setDatatype(columnsResultSet.getString("datatype"));
                        column.setSize(columnsResultSet.getInt("size"));
                        column.setPrincipal(columnsResultSet.getInt("principal") == 1);
+7 −2
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package it.inaf.oats.ia2.tap.tsm.datalayer;

import it.inaf.oats.ia2.tap.tsm.model.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@@ -100,12 +101,16 @@ public class TapSchemaDL {
                Schema schema = new Schema(connection, schemaName, tapSchema.getName(), tapSchema.toCreate());
                schema.setStatus(Status.SELECTED_SAVED);

                schema.setUtype(resultSet.getString("utype"));
                schema.setDescription(resultSet.getString("description"));
                schema.setValue(Schema.UTYPE, resultSet.getString("utype"));
                schema.setValue(Schema.DESCRIPTION, resultSet.getString("description"));
                // And schemaID ??

                tapSchema.addEntity(schemaName, schema);
            }
        }).read(connection);
    }

    public static void update(Credentials credentials, TapSchema tapSchema) {

    }
}
+363 −0
Original line number Diff line number Diff line
package it.inaf.oats.ia2.tap.tsm.datalayer;

import it.inaf.oats.ia2.tap.tsm.model.Column;
import it.inaf.oats.ia2.tap.tsm.model.Credentials;
import it.inaf.oats.ia2.tap.tsm.model.DbEntity;
import it.inaf.oats.ia2.tap.tsm.model.Key;
import it.inaf.oats.ia2.tap.tsm.model.KeyColumn;
import it.inaf.oats.ia2.tap.tsm.model.Schema;
import it.inaf.oats.ia2.tap.tsm.model.Status;
import it.inaf.oats.ia2.tap.tsm.model.Table;
import it.inaf.oats.ia2.tap.tsm.model.TapSchema;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;

/**
 *
 * @author Sonia Zorba <zorba at oats.inaf.it>
 */
public class UpdateManager {

    private final Credentials credentials;
    private final TapSchema tapSchema;

    private final ArrayList<Key> keysReaded;
    private final ArrayList<Integer> keysToRemove;

    private final ArrayList<Schema> schemasToAdd;
    private final ArrayList<Table> tablesToAdd;
    private final ArrayList<Column> columnsToAdd;

    private final ArrayList<String> schemasToRemove;
    private final ArrayList<String> tablesToRemove;
    private final ArrayList<String> columnsToRemove;

    private final ArrayList<Schema> schemasToUpdate;
    private final ArrayList<Table> tablesToUpdate;
    private final ArrayList<Column> columnsToUpdate;

    public UpdateManager(Credentials credentials, TapSchema tapSchema) {
        this.credentials = credentials;
        this.tapSchema = tapSchema;

        keysReaded = new ArrayList<Key>();
        keysToRemove = new ArrayList<Integer>();

        schemasToAdd = new ArrayList<Schema>();
        tablesToAdd = new ArrayList<Table>();
        columnsToAdd = new ArrayList<Column>();

        schemasToRemove = new ArrayList<String>();
        tablesToRemove = new ArrayList<String>();
        columnsToRemove = new ArrayList<String>();

        schemasToUpdate = new ArrayList<Schema>();
        tablesToUpdate = new ArrayList<Table>();
        columnsToUpdate = new ArrayList<Column>();
    }

    private void addKey(String fromTable, String targetTable, String fromColumn, String targetColumn) {
        Key key = null;
        for (Key k : keysReaded) {
            if (k.getFromTable().equals(fromTable) && k.getTargetTable().equals(targetTable)) {
                key = k;
            }
        }

        if (key == null) {
            key = new Key(fromTable, targetTable);
            keysReaded.add(key);
        }

        key.addKeyColumn(fromColumn, targetColumn);
    }

    public void update() {

        // Separate changes in specific lists
        for (DbEntity schemaDbEntity : tapSchema.getAllEntities()) {
            Schema schema = (Schema) schemaDbEntity;

            if (schema.getStatus() != Status.NOT_SELECTED) {

                switch (schema.getStatus()) {
                    case TO_REMOVE:
                        schemasToRemove.add(schema.getName());
                        break;
                    case SELECTED_TO_SAVE:
                        schemasToAdd.add(schema);
                        break;
                    case SELECTED_SAVED:
                        if (schema.hasChanges()) {
                            schemasToUpdate.add(schema);
                        }
                        break;
                }

                for (DbEntity tableDbEntity : schema.getAllEntities()) {
                    Table table = (Table) tableDbEntity;

                    if (table.getStatus() != Status.NOT_SELECTED) {

                        String tableName = table.getFullName();

                        switch (table.getStatus()) {
                            case TO_REMOVE:
                                tablesToRemove.add(tableName);
                                break;
                            case SELECTED_TO_SAVE:
                                if (schema.getStatus() == Status.SELECTED_SAVED || schema.getStatus() == Status.SELECTED_TO_SAVE) {
                                    tablesToAdd.add(table);
                                }
                                break;
                            case SELECTED_SAVED:
                                if (schema.getStatus() == Status.TO_REMOVE) {
                                    tablesToRemove.add(tableName);
                                } else if (table.hasChanges()) {
                                    tablesToUpdate.add(table);
                                }
                                break;
                        }

                        for (DbEntity columnDbEntity : table.getAllEntities()) {
                            Column column = (Column) columnDbEntity;

                            if (column.getStatus() != Status.NOT_SELECTED) {

                                String columnName = column.getName();

                                switch (column.getStatus()) {
                                    case TO_REMOVE:
                                        columnsToRemove.add(columnName);
                                        break;
                                    case SELECTED_TO_SAVE:
                                        if ((schema.getStatus() == Status.SELECTED_SAVED || schema.getStatus() == Status.SELECTED_TO_SAVE)
                                                && (table.getStatus() == Status.SELECTED_SAVED || table.getStatus() == Status.SELECTED_TO_SAVE)) {
                                            columnsToAdd.add(column);
                                        }
                                        break;
                                    case SELECTED_SAVED:
                                        if (schema.getStatus() == Status.TO_REMOVE || table.getStatus() == Status.TO_REMOVE) {
                                            columnsToRemove.add(columnName);
                                        } else if (column.hasChanges()) {
                                            columnsToUpdate.add(column);
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }

        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {

            connection = credentials.getConnection();
            
            /* ---------- Find keys to add ---------- */
            HashSet<String> schemasToCheck = new HashSet<String>(); // schema in which could be keys to add.
            for (Table table : tablesToAdd) {
                schemasToCheck.add(table.getSchemaName());
            }

            for (final String schemaName : schemasToCheck) {
                (new ResultSetReader("SELECT k.TABLE_NAME, k.COLUMN_NAME, "
                        + "k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME "
                        + "FROM information_schema.TABLE_CONSTRAINTS i "
                        + "LEFT JOIN information_schema.KEY_COLUMN_USAGE k "
                        + "ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME "
                        + "WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY' "
                        + "AND i.TABLE_SCHEMA = '" + schemaName + "' "
                        + "AND k.TABLE_SCHEMA = '" + schemaName + "'") {

                            @Override
                            public void manipulateItem(ResultSet resultSet) throws SQLException {
                                addKey(
                                        schemaName + "." + resultSet.getString("k.TABLE_NAME"),
                                        schemaName + "." + resultSet.getString("k.REFERENCED_TABLE_NAME"),
                                        resultSet.getString("k.COLUMN_NAME"),
                                        resultSet.getString("k.REFERENCED_COLUMN_NAME")
                                );
                            }
                        }).read(connection);
            }

            ArrayList<Key> keysToAdd = new ArrayList<Key>();
            for (Key key : keysReaded) {
                for (Table table : tablesToAdd) {
                    String tableName = table.getFullName();
                    if (key.getFromTable().equals(tableName) || key.getTargetTable().equals(tableName)) {
                        keysToAdd.add(key);
                    }
                }
            }

            // Use tapSchema database
            connection.setCatalog(tapSchema.getName());
            
            /* ---------- Find keys to remove ---------- */
            if (tablesToRemove.size() > 0) {

                String tablesToRemoveStr = "";
                for (int i = 0; i < tablesToRemove.size(); i++) {
                    tablesToRemoveStr += "'" + tablesToRemove.get(i) + "'";
                    if (i < tablesToRemove.size() - 1) {
                        tablesToRemoveStr += ",";
                    }
                }

                (new ResultSetReader("SELECT CAST(key_id AS UNSIGNED) key_id FROM `keys`\n"
                        + "WHERE from_table IN (" + tablesToRemoveStr + ") OR target_table IN (" + tablesToRemoveStr + ")") {

                            @Override
                            public void manipulateItem(ResultSet resultSet) throws SQLException {
                                keysToRemove.add(resultSet.getInt("key_id"));
                            }
                        }).read(connection);

            }
            
            /* ---------- Find max key id after keys removal ---------- */
            final ArrayList<Integer> maxKey = new ArrayList<Integer>();
            String query = "SELECT MAX(CAST(key_id AS UNSIGNED)) max_key from `keys`";

            if (keysToRemove.size() > 0) {
                String keysToRemoveStr = "";
                for (int i = 0; i < keysToRemove.size(); i++) {
                    keysToRemoveStr += "'" + keysToRemove.get(i) + "'";
                    if (i < keysToRemove.size() - 1) {
                        keysToRemoveStr += ",";
                    }
                }

                query += " WHERE key_id NOT IN (" + keysToRemoveStr + ")";
            }

            (new ResultSetReader(query) {

                @Override
                public void manipulateItem(ResultSet resultSet) throws SQLException {
                    maxKey.add(resultSet.getInt("max_key"));
                }
            }).read(connection);

            int newKeyId = maxKey.isEmpty() ? 1 : maxKey.get(0) + 1; // key id start offset

            // Start update
            connection.setAutoCommit(false); // start transaction

            // REMOVE ELEMENTS
            for (int keyId : keysToRemove) {
                statement = connection.prepareStatement("DELETE FROM key_columns WHERE key_id = ?");
                statement.setString(1, keyId + "");
                statement.executeUpdate();

                statement = connection.prepareStatement("DELETE FROM `keys` WHERE key_id = ?");
                statement.setString(1, keyId + "");
                statement.executeUpdate();
            }

            for (String columnName : columnsToRemove) {
                statement = connection.prepareStatement("DELETE FROM `columns` WHERE column_name = ?");
                statement.setString(1, columnName);
                statement.executeUpdate();
            }

            for (String tableFullName : tablesToRemove) {
                statement = connection.prepareStatement("DELETE FROM `tables` WHERE table_name = ?");
                statement.setString(1, tableFullName);
                statement.executeUpdate();
            }

            for (String schemaName : schemasToRemove) {
                statement = connection.prepareStatement("DELETE FROM `schemas` WHERE schema_name = ?");
                statement.setString(1, schemaName);
                statement.executeUpdate();
            }

            // INSERT ELEMENTS
            for (Schema schema : schemasToAdd) {
                schema.insert(connection);
            }

            for (Table table : tablesToAdd) {
                table.insert(connection);
            }

            for (Column column : columnsToAdd) {
                column.insert(connection);
            }

            for (Key key : keysToAdd) {
                statement = connection.prepareStatement("INSERT INTO `keys` "
                        + "(key_id, from_table, target_table, utype, description, keyID) "
                        + "VALUES(?,?,?,null,null,null)");
                statement.setString(1, newKeyId + "");
                statement.setString(2, key.getFromTable());
                statement.setString(3, key.getTargetTable());
                statement.executeUpdate();
                statement.close();

                for (KeyColumn kc : key.getKeyColumns()) {
                    statement = connection.prepareStatement("INSERT INTO key_columns "
                            + "(key_id, from_column, target_column, key_columnID) "
                            + "VALUES(?,?,?,null)");
                    statement.setString(1, newKeyId + "");
                    statement.setString(2, kc.getFromColumn());
                    statement.setString(3, kc.getTargetColumn());
                    statement.executeUpdate();
                    statement.close();
                }

                newKeyId++;
            }

            //UPDATE ELEMENTS
            for (Schema schema : schemasToUpdate) {
                schema.update(connection);
            }

            for (Table table : tablesToUpdate) {
                table.update(connection);
            }

            for (Column column : columnsToUpdate) {
                column.update(connection);
            }

            connection.commit();
        } catch (SQLException e) {
            try {
                if (connection != null && !connection.getAutoCommit()) {
                    connection.rollback();
                }
            } catch (SQLException ex) {
                ex.printStackTrace(System.err);
            }
            e.printStackTrace(System.err);
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException ex) {
                ex.printStackTrace(System.err);
            }
        }
    }
}
+143 −92

File changed.

Preview size limit exceeded, changes collapsed.

Loading