001: /*
002: * Created by IntelliJ IDEA.
003: * User: sg426575
004: * Date: Apr 23, 2006
005: * Time: 4:04:26 PM
006: */
007: package com.technoetic.xplanner.upgrade.schema;
008:
009: import java.lang.reflect.Method;
010: import java.sql.Connection;
011: import java.sql.ResultSet;
012: import java.sql.SQLException;
013: import java.sql.Statement;
014:
015: import org.apache.commons.lang.StringUtils;
016: import org.apache.log4j.Logger;
017: import org.springframework.dao.DataAccessException;
018: import org.springframework.jdbc.core.ConnectionCallback;
019: import org.springframework.jdbc.core.JdbcTemplate;
020: import org.springframework.jdbc.core.StatementCallback;
021: import org.springframework.jdbc.datasource.SingleConnectionDataSource;
022: import com.thoughtworks.proxy.factory.CglibProxyFactory;
023: import com.thoughtworks.proxy.toys.decorate.Decorating;
024: import com.thoughtworks.proxy.toys.decorate.InvocationDecoratorSupport;
025:
026: import com.technoetic.xplanner.util.LogUtil;
027:
028: /** @noinspection ClassWithTooManyMethods,RefusedBequest,LoopStatementThatDoesntLoop*/
029: public class DBSchemaMigrater {
030: protected static final Logger LOG = LogUtil.getLogger();
031:
032: private DBDialect dialect;
033: private JdbcTemplate template = new JdbcTemplate();
034:
035: public DBSchemaMigrater() {
036: } // for the proxy
037:
038: public DBSchemaMigrater(Connection connection) {
039: this .template = new JdbcTemplate(
040: new SingleConnectionDataSource(connection, true));
041: this .dialect = DBDialect.getDialect(template);
042: }
043:
044: public DBSchemaMigrater withNoException() {
045: return (DBSchemaMigrater) Decorating.object(
046: new Class[] { DBSchemaMigrater.class }, this ,
047: new InvocationDecoratorSupport() {
048: public Throwable decorateTargetException(
049: Object proxy, Method method, Object[] args,
050: Throwable cause) {
051: return null;
052: }
053:
054: public Exception decorateInvocationException(
055: Object proxy, Method method, Object[] args,
056: Exception cause) {
057: return null;
058: }
059:
060: public Object decorateResult(final Object proxy,
061: final Method method, final Object[] args,
062: final Object result) {
063: return result;
064: }
065:
066: }, new CglibProxyFactory());
067: }
068:
069: public void addForeignKeyConstraint(String table,
070: String constraintName, String foreignKey,
071: String referencedTable, String referencedKey) {
072: executeQuery(dialect.getAddForeignKeyConstraintQuery(table,
073: constraintName, foreignKey, referencedTable,
074: referencedKey));
075: }
076:
077: public void dropForeignKeyConstraint(String table,
078: String constraintName) {
079: executeQuery(dialect.getDropForeignKeyConstraintQuery(table,
080: constraintName));
081: }
082:
083: public void addUniqueConstraint(String table,
084: String constraintName, String column) {
085: executeQuery(dialect.getAddUniqueConstraintQuery(table,
086: constraintName, column));
087: }
088:
089: public void dropUniqueConstraint(String table, String constraintName) {
090: executeQuery(dialect.getDropUniqueConstraintQuery(table,
091: constraintName));
092: }
093:
094: public void createTable(String table, String fieldSQL) {
095: executeQuery(dialect.getCreateTableQuery(table, fieldSQL));
096: }
097:
098: public void dropTable(String table) {
099: executeQuery(dialect.getDropTableQuery(table));
100: }
101:
102: public void addIndex(String table, String name, String field,
103: boolean unique) {
104: executeQuery(dialect.getCreateIndexQuery(table, name, field,
105: unique));
106: }
107:
108: public void addPrimaryKey(String table, String primaryColumn) {
109: executeQuery(dialect.getAddPrimaryKeyQuery(table,
110: new String[] { primaryColumn }));
111: }
112:
113: public void addPrimaryKey(String table, String[] primaryColumns) {
114: executeQuery(dialect.getAddPrimaryKeyQuery(table,
115: primaryColumns));
116: }
117:
118: public void changePrimaryKey(String table, String[] primaryColumns) {
119: executeQuery(dialect.getChangePrimaryKeyQuery(table,
120: primaryColumns));
121: }
122:
123: public void changePrimaryKey(String table, String primaryColumn) {
124: executeQuery(dialect.getChangePrimaryKeyQuery(table,
125: new String[] { primaryColumn }));
126: }
127:
128: public void dropPrimaryKey(String table) {
129: executeQuery(dialect.getDropPrimaryKeyQuery(table));
130: }
131:
132: public void dropIndex(String table, String name) {
133: executeQuery(dialect.getDropIndexQuery(table, name));
134: }
135:
136: public void renameColumn(String table, String oldName,
137: String newName) {
138: executeQuery(dialect.getRenameColumnQuery(table, oldName,
139: newName, getColumnType(table, oldName)));
140: }
141:
142: private String getColumnType(final String table, final String name) {
143: return (String) template.execute(new ConnectionCallback() {
144: public Object doInConnection(Connection connection)
145: throws SQLException, DataAccessException {
146: ResultSet columns = connection.getMetaData()
147: .getColumns(null, null, table, name);
148: try {
149: if (columns.next()) {
150: return columns.getString("TYPE_NAME");
151: } else {
152: return null;
153: }
154: } finally {
155: columns.close();
156: }
157: }
158: });
159: }
160:
161: public boolean doesForeignKeyConstraintExist(final String table,
162: final String name) {
163: Boolean res = (Boolean) template
164: .execute(new ConnectionCallback() {
165: public Object doInConnection(Connection connection)
166: throws SQLException, DataAccessException {
167: ResultSet importedKeys = connection
168: .getMetaData().getImportedKeys(null,
169: null, table);
170: try {
171: return Boolean.valueOf(hasKeyWithName(
172: importedKeys, name));
173: } finally {
174: importedKeys.close();
175: }
176: }
177: });
178: return res.booleanValue();
179: }
180:
181: private static boolean hasKeyWithName(ResultSet keys, String name)
182: throws SQLException {
183: while (keys.next()) {
184: return keys.getString("FK_NAME").equals(name);
185: }
186: return false;
187: }
188:
189: private void executeQuery(final String sql) {
190: template.execute(new StatementCallback() {
191: public Object doInStatement(Statement statement)
192: throws SQLException, DataAccessException {
193: String[] lines = StringUtils.split(sql, ';');
194: for (int i = 0; i < lines.length; i++) {
195: String line = lines[i];
196: LOG.debug("Executing SQL " + line);
197: statement.execute(line);
198: }
199: return null;
200: }
201: });
202: }
203:
204: public boolean isHsql() {
205: return dialect instanceof HsqldbDBDialect;
206: }
207: }
|