001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdo.tools.ant;
012:
013: import org.apache.tools.ant.BuildException;
014:
015: import java.sql.Connection;
016: import java.sql.Statement;
017: import java.sql.SQLException;
018: import java.util.ArrayList;
019: import java.util.Iterator;
020: import java.util.Date;
021: import java.io.StringWriter;
022: import java.io.PrintWriter;
023: import java.io.File;
024: import java.io.FileOutputStream;
025: import java.text.SimpleDateFormat;
026:
027: import com.versant.core.jdbc.sql.diff.ControlParams;
028: import com.versant.core.jdbc.sql.SqlDriver;
029: import com.versant.core.jdbc.JdbcConnectionSource;
030: import com.versant.core.jdbc.JdbcStorageManagerFactory;
031:
032: /**
033: */
034: public class SchemaMigrationTask extends JdoTaskBase {
035:
036: private ControlParams params = null;
037: private boolean checkLength = true;
038: private boolean checkType = true;
039: private boolean checkScale = true;
040: private boolean checkNulls = true;
041: private boolean checkPK = true;
042: private boolean checkIndex = true;
043: private boolean checkConstraint = true;
044: private boolean checkExtraColumns = true;
045: private String outPutdir = null;
046: private boolean direct = false;
047:
048: public void setOutputdir(String dir) {
049: outPutdir = dir;
050: }
051:
052: public void setDirect(boolean direct) {
053: this .direct = direct;
054: }
055:
056: public void setDatastore(String datastore) {
057: // ignore - keep property for compatibility
058: }
059:
060: public void setCheckConstraint(boolean checkConstraint) {
061: this .checkConstraint = checkConstraint;
062: }
063:
064: public void setCheckExtraColumns(boolean checkExtraColumns) {
065: this .checkExtraColumns = checkExtraColumns;
066: }
067:
068: public void setCheckIndex(boolean checkIndex) {
069: this .checkIndex = checkIndex;
070: }
071:
072: public void setCheckLength(boolean checkLength) {
073: this .checkLength = checkLength;
074: }
075:
076: public void setCheckNulls(boolean checkNulls) {
077: this .checkNulls = checkNulls;
078: }
079:
080: public void setCheckPK(boolean checkPK) {
081: this .checkPK = checkPK;
082: }
083:
084: public void setCheckScale(boolean checkScale) {
085: this .checkScale = checkScale;
086: }
087:
088: public void setCheckType(boolean checkType) {
089: this .checkType = checkType;
090: }
091:
092: public void setOutPutdir(String outPutdir) {
093: this .outPutdir = outPutdir;
094: }
095:
096: public void execute()
097:
098: throws BuildException
099:
100: {
101: super .execute();
102:
103: params = new ControlParams();
104: params.setCheckConstraint(checkConstraint);
105: params.setCheckExtraColumns(checkExtraColumns);
106: params.setCheckIndex(checkIndex);
107: params.setCheckLength(checkLength);
108: params.setCheckNulls(checkNulls);
109: params.setCheckPK(checkPK);
110: params.setCheckScale(checkScale);
111: params.setCheckType(checkType);
112:
113: migrateDatabase();
114: }
115:
116: private String getFileName(SqlDriver sqlDriver) {
117: SimpleDateFormat formatter = new SimpleDateFormat(
118: "dd-MM-yyyy_H-m");
119: return "Schema_Migration_" + sqlDriver.getName() + "_"
120: + formatter.format(new Date());
121: }
122:
123: private void migrateDatabase()
124:
125: throws BuildException
126:
127: {
128: JdbcStorageManagerFactory jsmf = (JdbcStorageManagerFactory) innermostSmf;
129: JdbcConnectionSource conSrc = jsmf.getConnectionSource();
130: Connection con = null;
131: FileOutputStream fout = null;
132: PrintWriter out = null;
133: try {
134: log("Checking schema on " + conSrc.getURL());
135: StringWriter error = new StringWriter();
136: PrintWriter perror = new PrintWriter(error, false);
137:
138: StringWriter fix = new StringWriter();
139: PrintWriter pfix = new PrintWriter(fix, false);
140:
141: con = conSrc.getConnection(false, false);
142: boolean valid = jsmf.getSqlDriver().checkDDL(
143: jsmf.getJdbcMetaData().getTables(), con, perror,
144: pfix, params);
145: perror.close();
146: pfix.close();
147: if (valid) {
148: log("Schema is valid.");
149: } else {
150: log("Schema has errors.");
151: log(error.toString());
152: error.close();
153:
154: if (outPutdir != null) {
155: File f = new File(outPutdir, getFileName(jsmf
156: .getSqlDriver())
157: + ".sql");
158: fout = new FileOutputStream(f);
159: out = new PrintWriter(fout);
160: out.write(fix.toString());
161: out.flush();
162: out.close();
163: }
164:
165: if (direct) {
166: runScript(con, fix.toString());
167: }
168:
169: }
170: } catch (Exception x) {
171: throwBuildException(x.getClass().getName() + ": "
172: + x.getMessage(), x);
173: } finally {
174: if (con != null) {
175: try {
176: conSrc.returnConnection(con);
177: } catch (SQLException e) {
178: // ignore
179: }
180: }
181: }
182: }
183:
184: public void runScript(Connection con, String script)
185: throws Exception {
186: if (!con.getAutoCommit()) {
187: con.rollback();
188: con.setAutoCommit(true);
189: }
190:
191: SQLScriptParser shredder = new SQLScriptParser();
192: ArrayList list = shredder.parse(script, true);
193: for (Iterator iter = list.iterator(); iter.hasNext();) {
194: SQLScriptParser.SQLScriptPart scriptPart = (SQLScriptParser.SQLScriptPart) iter
195: .next();
196: log("Executing: " + scriptPart.getSql());
197: Statement stat = null;
198: try {
199: stat = con.createStatement();
200: stat.execute(scriptPart.getSql());
201: } finally {
202: try {
203: stat.close();
204: } catch (SQLException e) {
205: //hide
206: }
207: }
208: }
209: }
210: }
|