001: /*
002: * ProcedureCreator.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.db;
013:
014: import java.sql.SQLException;
015: import java.sql.Statement;
016: import java.util.Iterator;
017: import java.util.LinkedList;
018: import java.util.List;
019: import workbench.db.oracle.OraclePackageParser;
020: import workbench.log.LogMgr;
021: import workbench.sql.formatter.SQLLexer;
022: import workbench.sql.formatter.SQLToken;
023: import workbench.util.SqlUtil;
024:
025: /**
026: * @author support@sql-workbench.net
027: */
028: public class ProcedureCreator {
029: private String sourceSql;
030: private WbConnection dbConnection;
031: private String procedureSchema;
032: private String procedureName;
033: private boolean isReplaceScript;
034:
035: public ProcedureCreator(WbConnection con, String procSchema,
036: String procName, String procSource) {
037: this .sourceSql = procSource;
038: this .dbConnection = con;
039: this .procedureSchema = procSchema;
040: this .procedureName = procName;
041: }
042:
043: private void dropIfNecessary() throws SQLException {
044: if (this .isReplaceScript)
045: return;
046:
047: StringBuilder sql = new StringBuilder(50);
048: sql.append("DROP ");
049: sql.append(getType());
050: sql.append(' ');
051:
052: if (procedureSchema != null) {
053: sql.append(procedureSchema);
054: sql.append('.');
055: }
056:
057: sql.append(procedureName);
058: Statement stmt = null;
059: try {
060: stmt = this .dbConnection.createStatement();
061: stmt.executeUpdate(sql.toString());
062: } finally {
063: SqlUtil.closeStatement(stmt);
064: }
065: }
066:
067: private String getType() {
068: String type = null;
069: try {
070: SQLLexer lexer = new SQLLexer(this .sourceSql);
071: SQLToken t = lexer.getNextToken(false, false);
072: boolean nextTokenIsType = false;
073: while (t != null) {
074: String v = t.getContents();
075: if ("CREATE".equals(v)) {
076: nextTokenIsType = true;
077: } else if (nextTokenIsType && "OR".equalsIgnoreCase(v)) {
078: // waiting for REPLACE
079: nextTokenIsType = false;
080: } else if ("REPLACE".equalsIgnoreCase(v)) {
081: isReplaceScript = true;
082: nextTokenIsType = true;
083: } else if (nextTokenIsType) {
084: type = t.getContents();
085: break;
086: }
087: t = lexer.getNextToken(false, false);
088: }
089: } catch (Exception e) {
090: type = null;
091: }
092: return type;
093: }
094:
095: public void recreate() throws SQLException {
096: if (this .dbConnection.isBusy())
097: return;
098:
099: Statement stmt = null;
100: try {
101: this .dbConnection.setBusy(true);
102: dropIfNecessary();
103: stmt = this .dbConnection.createStatement();
104:
105: List<String> sqls = this .parseScript();
106: Iterator itr = sqls.iterator();
107: while (itr.hasNext()) {
108: String sql = this .dbConnection.getMetadata().filterDDL(
109: (String) itr.next());
110: stmt.executeUpdate(sql);
111: }
112:
113: if (dbConnection.shouldCommitDDL()) {
114: this .dbConnection.commit();
115: }
116: } catch (SQLException e) {
117: LogMgr.logError("ProcedureCreator.recreate()",
118: "Error when recreating procedure", e);
119: if (dbConnection.shouldCommitDDL()) {
120: try {
121: this .dbConnection.rollback();
122: } catch (Throwable th) {
123: }
124: }
125: throw e;
126: } finally {
127: SqlUtil.closeStatement(stmt);
128: this .dbConnection.setBusy(false);
129: }
130: }
131:
132: private List<String> parseScript() {
133: List<String> result = new LinkedList<String>();
134: if (this .dbConnection.getMetadata().isOracle()) {
135: OraclePackageParser parser = new OraclePackageParser(
136: this .sourceSql);
137: String sql = null;
138:
139: sql = parser.getPackageDeclaration();
140: if (sql != null)
141: result.add(sql);
142: sql = parser.getPackageBody();
143: if (sql != null)
144: result.add(sql);
145: if (result.size() == 0) {
146: // not package detected, use the whole script
147: result.add(this.sourceSql);
148: }
149: } else {
150: result.add(this.sourceSql);
151: }
152: return result;
153: }
154:
155: }
|