/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program 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 version 2 of the License. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.core.db.setup; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.rhq.core.db.DatabaseTypeFactory; /** * Tracks a ResultSet. Call {@link #next()} to go to the next row. Call {@link #getData(int)} to get a column within the * current row. */ abstract class DataSet { private DBSetup m_parent; private String m_strTableName; protected DataSet(String tableName, DBSetup dbsetup) { this.m_strTableName = tableName; this.m_parent = dbsetup; } protected int create() throws SQLException { int rowcnt = 0; try { executePreCreateCommands(); // loop through each row for (; this.next(); rowcnt++) { String strCmd = this.getCreateCommand(); doSQL(strCmd); } executePostCreateCommands(); } catch (SQLException e) { try { this.m_parent.getConnection().rollback(); } catch (Exception e2) { e2.printStackTrace(); } throw e; } return rowcnt; // The number of rows created. } protected void doSQL(String sql) throws SQLException { m_parent.doSQL(sql); } protected void executePreCreateCommands() throws SQLException { } protected void executePostCreateCommands() throws SQLException { } /** * Get the statement to create the data - this may be an INSERT or it may be an UPDATE. If key columns where * specified in the data, then assume we want to UPDATE the row using they key columns for the WHERE clause. * Otherwise, assume its a new row to be INSERTED. * * @return SQL statement to create the data. * * @throws SQLException */ protected String getCreateCommand() throws SQLException { String cmd; if (keyColumnsExist()) { cmd = getUpdateCommand(); } else { cmd = getInsertCommand(); } return cmd; } protected String getInsertCommand() throws SQLException { int iCols = this.getNumberColumns(); StringBuilder strCmd = new StringBuilder("INSERT INTO "); strCmd.append(this.getTableName()); strCmd.append(" ("); for (int i = 0; i < iCols; i++) { Data data = this.getData(i); if (i > 0) { strCmd.append(','); } strCmd.append(data.getColumnName()); } strCmd.append(") VALUES ("); for (int i = 0; i < iCols; i++) { if (i > 0) { strCmd.append(','); } String strValue = getData(i).getValue(); if (strValue != null) { // We need to replace the value 'TRUE' with '1' if this is // Oracle. It's a hack to have this code in this class until I // do some restructuring of the code if (DatabaseTypeFactory.isOracle(m_parent.getDatabaseType()) || DatabaseTypeFactory.isSQLServer(m_parent.getDatabaseType())) { if (strValue.equalsIgnoreCase("TRUE")) { strValue = "1"; } else if (strValue.equalsIgnoreCase("FALSE")) { strValue = "0"; } } strCmd.append('\''); strCmd.append(strValue); strCmd.append('\''); } else { strCmd.append("NULL"); } } strCmd.append(')'); return strCmd.toString(); } protected String getUpdateCommand() throws SQLException { int iCols = this.getNumberColumns(); StringBuilder strCmd = new StringBuilder("UPDATE "); strCmd.append(this.getTableName()); strCmd.append(" SET "); boolean need_comma = false; for (int i = 0; i < iCols; i++) { Data data = this.getData(i); if (data.isKeyColumn()) { continue; } if (need_comma) { strCmd.append(','); } need_comma = true; strCmd.append(data.getColumnName()); strCmd.append(" = "); String strValue = data.getValue(); if (strValue != null) { // We need to replace the value 'TRUE' with '1' if this is // Oracle. It's a hack to have this code in this class until I // do some restructuring of the code if (DatabaseTypeFactory.isOracle(m_parent.getDatabaseType()) || DatabaseTypeFactory.isSQLServer(m_parent.getDatabaseType())) { if (strValue.equalsIgnoreCase("TRUE")) { strValue = "1"; } else if (strValue.equalsIgnoreCase("FALSE")) { strValue = "0"; } } strCmd.append('\''); strCmd.append(strValue); strCmd.append('\''); } else { strCmd.append("NULL"); } } strCmd.append(" WHERE "); boolean need_AND_keyword = false; List<Data> keys = getKeyColumns(); for (Data data : keys) { if (need_AND_keyword) { strCmd.append(" AND "); } need_AND_keyword = true; strCmd.append(data.getActualColumnName()).append(" = "); String key_value = data.getValue(); if (key_value != null) { // We need to replace the value 'TRUE' with '1' if this is // Oracle. It's a hack to have this code in this class until I // do some restructuring of the code if (DatabaseTypeFactory.isOracle(m_parent.getDatabaseType()) || DatabaseTypeFactory.isSQLServer(m_parent.getDatabaseType())) { if (key_value.equalsIgnoreCase("TRUE")) { key_value = "1"; } else if (key_value.equalsIgnoreCase("FALSE")) { key_value = "0"; } } strCmd.append('\''); strCmd.append(key_value); strCmd.append('\''); } else { strCmd.append("NULL"); } } return strCmd.toString(); } protected int getNumberColumns() { return 0; } protected String getTableName() { return this.m_strTableName; } protected boolean keyColumnsExist() { int num_col = getNumberColumns(); for (int i = 0; i < num_col; i++) { Data data = getData(i); if (data == null) { System.err.println("Data at column index for table " + m_strTableName + " is null"); } else if (data.isKeyColumn()) { return true; } } return false; } protected List<Data> getKeyColumns() { List<Data> keys = new ArrayList<Data>(); int num_col = getNumberColumns(); for (int i = 0; i < num_col; i++) { Data data = getData(i); if (data == null) { System.err.println("Data at column index for table " + m_strTableName + " is null"); } else if (data.isKeyColumn()) { keys.add(data); } } return keys; } protected abstract Data getData(int columnIndex); protected abstract boolean next(); }