/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.tools.db; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; import java.util.List; import java.util.Iterator; import org.hyperic.util.StringList; import org.hyperic.util.StrongCollection; import org.hyperic.util.jdbc.JDBC; import org.xml.sax.SAXException; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; class Table { private DBSetup m_parent; private String m_strName; private boolean m_indexOrganized = false; // Index Organized Table private boolean m_parallel = false; // Parallel processing private boolean m_logging = false; private boolean m_cache = false; private String m_tableSpace; private String m_storage; private String m_engine; private List m_listColumns; private Collection m_collIndexes; private Collection m_collConstraints; private DataSet m_dataset; protected Table() {} protected Table(Node node, int dbtype, DBSetup dbsetup) throws SAXException { m_parent = dbsetup; if(Table.isTable(node)) { NamedNodeMap map = node.getAttributes(); for(int iTab = 0;iTab < map.getLength();iTab++) { Node nodeMap = map.item(iTab); if(nodeMap.getNodeName().equalsIgnoreCase("name")) { this.m_strName = nodeMap.getNodeValue(); } else if(nodeMap.getNodeName().equalsIgnoreCase( "index-organized")) { this.m_indexOrganized = nodeMap.getNodeValue().equalsIgnoreCase("true"); } else if(nodeMap.getNodeName().equalsIgnoreCase( "parallel")) { this.m_parallel = nodeMap.getNodeValue().equalsIgnoreCase("true"); } else if(nodeMap.getNodeName().equalsIgnoreCase( "logging")) { this.m_logging = nodeMap.getNodeValue().equalsIgnoreCase("true"); } else if(nodeMap.getNodeName().equalsIgnoreCase( "cache")) { this.m_cache = nodeMap.getNodeValue().equalsIgnoreCase("true"); } else if(nodeMap.getNodeName().equalsIgnoreCase( "tablespace")) { this.m_tableSpace = nodeMap.getNodeValue(); } else if(nodeMap.getNodeName().equalsIgnoreCase( "storage-options")) { this.m_storage = nodeMap.getNodeValue(); } else if(nodeMap.getNodeName().equalsIgnoreCase( "engine")) { this.m_engine = nodeMap.getNodeValue(); } else if(m_parent.isVerbose()) { System.out.println( "Unknown attribute \'" + nodeMap.getNodeName() + "\' in tag \'table\'"); } } this.m_listColumns = Column.getColumns(node, this, dbtype); this.m_collIndexes = Index.getIndexes(this, node, dbtype); this.m_collConstraints = Constraint.getConstraints(this, node, dbtype); this.m_dataset = new XmlDataSet(this, node); } else { throw new SAXException("node is not a table."); } } protected Table(ResultSet set, DatabaseMetaData meta, DBSetup dbsetup) throws SQLException { this.m_parent = dbsetup; this.m_strName = set.getString(3); this.m_listColumns = Column.getColumns(meta, this); this.m_dataset = new SqlDataSet(this); } protected void create(Collection typemaps) throws SQLException { List collCmds = new java.util.Vector(); this.getCreateCommands(collCmds, typemaps, JDBC.toType(m_parent.getConn().getMetaData().getURL())); Iterator iter = collCmds.iterator(); while(iter.hasNext()) { String strCmd = (String)iter.next(); m_parent.doSQL(strCmd); } } private void doCmd(List collCmds) throws SQLException { Iterator iter = collCmds.iterator(); while(iter.hasNext()) { String strCmd = (String)iter.next(); m_parent.doSQL(strCmd); } } protected void clear() throws SQLException { List collCmds = new StringList(); this.getClearCommands(collCmds); doCmd(collCmds); } protected void drop() throws SQLException { List collCmds = new StringList(); this.getDropCommands(collCmds); doCmd(collCmds); } protected List getColumns() { return this.m_listColumns; } protected String getTableSpace() { return this.m_tableSpace; } protected String getStorage() { return this.m_storage; } protected String getEngine() { return this.m_engine; } protected void getCreateCommands(List cmds, Collection typemaps, int dbtype) { String strCmd = "CREATE TABLE " + this.getName() + " ("; Iterator iter = this.getColumns().iterator(); boolean bFirst = true; List preCreateCommands = new StringList(); List postCreateCommands = new StringList(); Column col = null; while(iter.hasNext()) { if(bFirst) bFirst = false; else strCmd += ", "; col = (Column) iter.next(); col.getPreCreateCommands(preCreateCommands); strCmd += col.getCreateCommand(cmds, typemaps, dbtype); col.getPostCreateCommands(postCreateCommands); } // Add constraint decls iter = this.getConstraints().iterator(); Constraint constraint = null; while ( iter.hasNext() ) { constraint = (Constraint) iter.next(); strCmd += constraint.getCreateString(); constraint.getPostCreateCommands(postCreateCommands); } strCmd += ')'; if(this.m_indexOrganized) strCmd += this.getIndexOrganizedSyntax(dbtype); // deal with the special tablespace attr if (this.m_tableSpace != null && !this.m_tableSpace.equals("DEFAULT") && !this.getTableSpaceSyntax().equals("")) { strCmd += this.getTableSpaceSyntax() + this.getTableSpace(); } // add a storage clause if any apply strCmd += this.getStorageClause(); if(this.m_parallel) strCmd += this.getParallelSyntax(); if(!this.m_logging) // Oracle does NOLOGGING strCmd += this.getLoggingSyntax(); if(this.m_cache) strCmd += this.getCacheSyntax(); cmds.addAll(preCreateCommands); cmds.add(strCmd); cmds.addAll(postCreateCommands); } /** * Get the storage clause for this table. Returns an empty string if * it is not applicable * @return */ public String getStorageClause() { if(this.m_storage != null && !this.getStorageSyntax().equals("")) { return this.getStorageSyntax() + "(" + m_storage + ")"; } else { return ""; } } /** * Get the engine clause for this table. Returns an empty string if * not applicable */ public String getEngineClause() { // if(this.m_engine != null && !this.getEngineSyntax().equals("")) { // return this.getEngineSyntax() + "(" + m_engine + ")"; // } // FIXME hardcoded to all tables w/ same engine clause if engine is supported if(!this.getEngineSyntax().equals("")) { return this.getEngineSyntax(); } else { return ""; } } protected String getIndexOrganizedSyntax(int dbtype) { return (dbtype == OracleTable.CLASS_TYPE) ? " ORGANIZATION INDEX" : ""; } protected String getParallelSyntax() { return ""; } protected String getLoggingSyntax() { return ""; } protected String getCacheSyntax() { return ""; } protected String getTableSpaceSyntax() { return ""; } protected String getStorageSyntax() { return ""; } protected String getEngineSyntax() { return ""; } protected DataSet getDataSet() { return this.m_dataset; } protected void getClearCommands(List cmds) { String strCmd = "DELETE FROM " + this.getName(); cmds.add(strCmd); } protected void getDropCommands(List cmds) { String strCmd = "DROP TABLE " + this.getName(); cmds.add(strCmd); Iterator iter = this.getColumns().iterator(); while(iter.hasNext()) ((Column)iter.next()).getDropCommands(cmds); } protected Collection getConstraints() { return this.m_collConstraints; } protected Collection getIndexes() { return this.m_collIndexes; } protected String getQueryCommand() { String strCmd = "SELECT "; Iterator iter = this.getColumns().iterator(); while(iter.hasNext()) { strCmd += ((Column)iter.next()).getName(); if(iter.hasNext()) strCmd += ','; strCmd += ' '; } strCmd = strCmd + "FROM " + this.getName(); return strCmd; } protected String getName() { return this.m_strName.toUpperCase(); } protected static Collection<Table> getTables(Node node, int dbtype, DBSetup parent) { Collection<Table> colResult = new StrongCollection("org.hyperic.tools.db.Table"); NodeList listTabs = node.getChildNodes(); String strTmp = node.getNodeName(); for (int iTab = 0; iTab < listTabs.getLength(); iTab++) { Node nodeTab = listTabs.item(iTab); if (Table.isTable(nodeTab)) { try { switch (dbtype) { case OracleTable.CLASS_TYPE : colResult.add( new OracleTable(nodeTab, dbtype, parent)); break; case MySQLTable.CLASS_TYPE : colResult.add( new MySQLTable(nodeTab, dbtype, parent)); break; default : colResult.add(new Table(nodeTab, dbtype, parent)); break; } } catch (SAXException e) { } } } return colResult; } protected static Collection<Table> getTables(DBSetup parent, String username) throws SQLException { int dbtype = JDBC.toType(parent.getConn().getMetaData().getURL()); // when exporting a database, the particulars of how the metadata // with the list of tables is accessed is likely very driver-specific switch (dbtype) { case OracleTable.CLASS_TYPE: return OracleTable.getTables(parent, username); case CloudscapeTable.CLASS_TYPE: return CloudscapeTable.getTables(parent, username); } if(username != null) username = username.toUpperCase(); Collection<Table> coll = new StrongCollection("org.hyperic.tools.db.Table"); DatabaseMetaData meta = parent.getConn().getMetaData(); String[] types = {"TABLE"}; // there doesn't seem to be a general case for this but we // know this works for Oracle, so we'll start there ResultSet setTabs = meta.getTables(null, username, "%", types); // Find Tables while(setTabs.next()) coll.add(new Table(setTabs, meta, parent)); return coll; } protected static boolean isTable(Node nodeTable) { return nodeTable.getNodeName().equalsIgnoreCase("table"); } // Can be overridden to do cleanup on an uninstall protected static void uninstallCleanup(DBSetup parent) throws SQLException { int dbtype = JDBC.toType(parent.getConn().getMetaData().getURL()); if( dbtype == PointbaseTable.getClassType() ) PointbaseTable.uninstallCleanup(parent.getConn()); } protected DBSetup getDBSetup () { return m_parent; } }