001: /*
002: * CommandMapper.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.sql;
013:
014: import java.util.HashMap;
015: import java.util.LinkedList;
016: import java.util.List;
017: import workbench.WbManager;
018: import workbench.db.DbMetadata;
019: import workbench.db.DbMetadata;
020: import workbench.db.WbConnection;
021: import workbench.log.LogMgr;
022: import workbench.resource.Settings;
023: import workbench.sql.commands.AlterSessionCommand;
024: import workbench.sql.commands.DdlCommand;
025: import workbench.sql.commands.IgnoredCommand;
026: import workbench.sql.commands.SelectCommand;
027: import workbench.sql.commands.SetCommand;
028: import workbench.sql.commands.SingleVerbCommand;
029: import workbench.sql.commands.UpdatingCommand;
030: import workbench.sql.commands.UseCommand;
031: import workbench.sql.wbcommands.WbCall;
032: import workbench.sql.wbcommands.WbConfirm;
033: import workbench.sql.wbcommands.WbConnect;
034: import workbench.sql.wbcommands.WbCopy;
035: import workbench.sql.wbcommands.WbDefinePk;
036: import workbench.sql.wbcommands.WbDefineVar;
037: import workbench.sql.wbcommands.WbDescribeTable;
038: import workbench.sql.wbcommands.WbDisableOraOutput;
039: import workbench.sql.wbcommands.WbEnableOraOutput;
040: import workbench.sql.wbcommands.WbEndBatch;
041: import workbench.sql.wbcommands.WbExport;
042: import workbench.sql.wbcommands.WbFeedback;
043: import workbench.sql.wbcommands.WbImport;
044: import workbench.sql.wbcommands.WbInclude;
045: import workbench.sql.wbcommands.WbListCatalogs;
046: import workbench.sql.wbcommands.WbListPkDef;
047: import workbench.sql.wbcommands.WbListProcedures;
048: import workbench.sql.wbcommands.WbListTables;
049: import workbench.sql.wbcommands.WbListVars;
050: import workbench.sql.wbcommands.WbLoadPkMapping;
051: import workbench.sql.wbcommands.WbRemoveVar;
052: import workbench.sql.wbcommands.WbSavePkMapping;
053: import workbench.sql.wbcommands.WbSchemaDiff;
054: import workbench.sql.wbcommands.WbSchemaReport;
055: import workbench.sql.wbcommands.WbSelectBlob;
056: import workbench.sql.wbcommands.WbStartBatch;
057: import workbench.sql.wbcommands.WbXslt;
058: import workbench.util.SqlUtil;
059: import workbench.util.StringUtil;
060:
061: /**
062: * @author support@sql-workbench.net
063: */
064: public class CommandMapper {
065: private HashMap<String, SqlCommand> cmdDispatch;
066: private List<String> dbSpecificCommands;
067: private boolean supportsSelectInto = false;
068: private DbMetadata metaData;
069:
070: public CommandMapper() {
071: cmdDispatch = new HashMap<String, SqlCommand>();
072: cmdDispatch.put("*", new SqlCommand());
073:
074: SqlCommand sql = new WbListTables();
075: cmdDispatch.put(sql.getVerb(), sql);
076:
077: sql = new WbListProcedures();
078: cmdDispatch.put(sql.getVerb(), sql);
079:
080: sql = new WbDescribeTable();
081: cmdDispatch.put(sql.getVerb(), sql);
082: cmdDispatch.put("DESCRIBE", sql);
083:
084: sql = new WbEnableOraOutput();
085: cmdDispatch.put(sql.getVerb(), sql);
086:
087: sql = new WbDisableOraOutput();
088: cmdDispatch.put(sql.getVerb(), sql);
089:
090: sql = new WbStartBatch();
091: cmdDispatch.put(sql.getVerb(), sql);
092:
093: sql = new WbEndBatch();
094: cmdDispatch.put(sql.getVerb(), sql);
095:
096: sql = new SelectCommand();
097: cmdDispatch.put(sql.getVerb(), sql);
098:
099: sql = new WbXslt();
100: cmdDispatch.put(sql.getVerb(), sql);
101: cmdDispatch.put("XSLT", sql);
102:
103: cmdDispatch.put(WbDefineVar.DEFINE_LONG.getVerb(),
104: WbDefineVar.DEFINE_LONG);
105: cmdDispatch.put(WbDefineVar.DEFINE_SHORT.getVerb(),
106: WbDefineVar.DEFINE_SHORT);
107:
108: sql = new WbRemoveVar();
109: cmdDispatch.put(sql.getVerb(), sql);
110:
111: sql = new WbListVars();
112: cmdDispatch.put(sql.getVerb(), sql);
113:
114: sql = new WbExport();
115: cmdDispatch.put(sql.getVerb(), sql);
116:
117: sql = new WbImport();
118: cmdDispatch.put(sql.getVerb(), sql);
119:
120: sql = new WbCopy();
121: cmdDispatch.put(sql.getVerb(), sql);
122:
123: sql = new WbSchemaReport();
124: cmdDispatch.put(sql.getVerb(), sql);
125:
126: sql = new WbSchemaDiff();
127: cmdDispatch.put(sql.getVerb(), sql);
128:
129: sql = new SetCommand();
130: cmdDispatch.put(sql.getVerb(), sql);
131:
132: sql = new WbFeedback();
133: cmdDispatch.put(sql.getVerb(), sql);
134:
135: sql = new WbDefinePk();
136: cmdDispatch.put(sql.getVerb(), sql);
137:
138: sql = new WbListPkDef();
139: cmdDispatch.put(sql.getVerb(), sql);
140:
141: sql = new WbLoadPkMapping();
142: cmdDispatch.put(sql.getVerb(), sql);
143:
144: sql = new WbSavePkMapping();
145: cmdDispatch.put(sql.getVerb(), sql);
146:
147: sql = new WbConfirm();
148: cmdDispatch.put(sql.getVerb(), sql);
149:
150: sql = new WbCall();
151: cmdDispatch.put(sql.getVerb(), sql);
152:
153: if (WbManager.getInstance().isBatchMode()) {
154: sql = new WbConnect();
155: cmdDispatch.put(sql.getVerb(), sql);
156: }
157:
158: cmdDispatch.put(WbInclude.INCLUDE_LONG.getVerb(),
159: WbInclude.INCLUDE_LONG);
160: cmdDispatch.put(WbInclude.INCLUDE_SHORT.getVerb(),
161: WbInclude.INCLUDE_SHORT);
162:
163: cmdDispatch.put(WbListCatalogs.LISTCAT.getVerb(),
164: WbListCatalogs.LISTCAT);
165: cmdDispatch.put(WbListCatalogs.LISTDB.getVerb(),
166: WbListCatalogs.LISTDB);
167:
168: cmdDispatch.put(SingleVerbCommand.COMMIT.getVerb(),
169: SingleVerbCommand.COMMIT);
170: cmdDispatch.put(SingleVerbCommand.ROLLBACK.getVerb(),
171: SingleVerbCommand.ROLLBACK);
172:
173: cmdDispatch.put(UpdatingCommand.DELETE.getVerb(),
174: UpdatingCommand.DELETE);
175: cmdDispatch.put(UpdatingCommand.INSERT.getVerb(),
176: UpdatingCommand.INSERT);
177: cmdDispatch.put(UpdatingCommand.UPDATE.getVerb(),
178: UpdatingCommand.UPDATE);
179: cmdDispatch.put(UpdatingCommand.TRUNCATE.getVerb(),
180: UpdatingCommand.TRUNCATE);
181:
182: cmdDispatch.put(WbSelectBlob.VERB, new WbSelectBlob());
183:
184: for (DdlCommand cmd : DdlCommand.DDL_COMMANDS) {
185: cmdDispatch.put(cmd.getVerb(), cmd);
186: }
187: this .cmdDispatch.put("CREATE OR REPLACE", DdlCommand.CREATE);
188:
189: this .dbSpecificCommands = new LinkedList<String>();
190: }
191:
192: /**
193: * For testing purposes, to that non-default commands can be added
194: * during a JUnit test
195: */
196: public void addCommand(SqlCommand command) {
197: cmdDispatch.put(command.getVerb(), command);
198: }
199:
200: /**
201: * Initialize the CommandMapper with a database connection.
202: * This will add DBMS specific commands to the internal dispatch.
203: *
204: * This method can be called multiple times.
205: */
206: public void setConnection(WbConnection aConn) {
207: for (String cmd : dbSpecificCommands) {
208: this .cmdDispatch.remove(cmd);
209: }
210: this .dbSpecificCommands.clear();
211: this .supportsSelectInto = false;
212:
213: if (aConn == null)
214: return;
215:
216: this .metaData = aConn.getMetadata();
217:
218: if (metaData == null) {
219: LogMgr.logError("CommandMapper.setConnection()",
220: "Received connection without metaData!", null);
221: return;
222: }
223:
224: if (metaData.isOracle()) {
225: SqlCommand wbcall = this .cmdDispatch.get(WbCall.VERB);
226:
227: this .cmdDispatch.put(WbCall.EXEC_VERB_LONG, wbcall);
228: this .cmdDispatch.put(WbCall.EXEC_VERB_SHORT, wbcall);
229:
230: AlterSessionCommand alter = new AlterSessionCommand();
231: this .cmdDispatch.put(alter.getVerb(), alter);
232:
233: WbFeedback echo = new WbFeedback("ECHO");
234: this .cmdDispatch.put(echo.getVerb(), echo);
235:
236: this .dbSpecificCommands.add(alter.getVerb());
237: this .dbSpecificCommands.add(WbCall.EXEC_VERB_LONG);
238: this .dbSpecificCommands.add(WbCall.EXEC_VERB_SHORT);
239: this .dbSpecificCommands.add(echo.getVerb());
240: } else if (metaData.isSqlServer() || metaData.isMySql()
241: || metaData.supportsCatalogs()) {
242: UseCommand cmd = new UseCommand();
243: this .cmdDispatch.put(cmd.getVerb(), cmd);
244: this .dbSpecificCommands.add(cmd.getVerb());
245: } else if (metaData.isFirebird()) {
246: this .cmdDispatch.put(DdlCommand.RECREATE.getVerb(),
247: DdlCommand.RECREATE);
248: this .cmdDispatch.put(WbInclude.INCLUDE_FB.getVerb(),
249: WbInclude.INCLUDE_FB);
250: this .dbSpecificCommands.add(WbInclude.INCLUDE_FB.getVerb());
251: this .dbSpecificCommands.add(DdlCommand.RECREATE.getVerb());
252: }
253:
254: if (metaData.getDbSettings().useWbProcedureCall()) {
255: SqlCommand wbcall = this .cmdDispatch.get(WbCall.VERB);
256: this .cmdDispatch.put("CALL", wbcall);
257: this .dbSpecificCommands.add("CALL");
258: }
259:
260: String verbs = Settings.getInstance().getProperty(
261: "workbench.db.ignore." + metaData.getDbId(), "");
262: List l = StringUtil.stringToList(verbs, ",", true, true);
263: for (int i = 0; i < l.size(); i++) {
264: String verb = (String) l.get(i);
265: if (verb == null)
266: continue;
267: verb = verb.toUpperCase();
268: IgnoredCommand cmd = new IgnoredCommand(verb);
269: this .cmdDispatch.put(verb, cmd);
270: this .dbSpecificCommands.add(verb);
271: }
272:
273: // this is stored in an instance variable for performance
274: // reasons, so we can skip the call to isSelectIntoNewTable() in
275: // getCommandToUse()
276: // For a single call this doesn't matter, but when executing
277: // huge scripts the repeated call to getCommandToUse should
278: // be as quick as possible
279: this .supportsSelectInto = metaData.supportsSelectIntoNewTable();
280: }
281:
282: /**
283: * Check for a SELECT ... INTO syntax for Informix which actually
284: * creates a table. In that case we will simply pretend it's a
285: * CREATE statement.
286: * In all other casese, the approriate SqlCommand from commanDispatch will be used
287: * This is made public in order to be accessible from a JUnit test
288: *
289: * @param sql the statement to be executed
290: * @return the instance of SqlCommand to be used to run the sql, or null if the
291: * given sql is empty or contains comments only
292: */
293: public SqlCommand getCommandToUse(String sql) {
294: SqlCommand cmd = null;
295: String verb = SqlUtil.getSqlVerb(sql);
296: if (StringUtil.isEmptyString(verb))
297: return null;
298:
299: if (this .supportsSelectInto && this .metaData != null
300: && this .metaData.isSelectIntoNewTable(sql)) {
301: LogMgr.logDebug("CommandMapper.getCommandToUse()",
302: "Found 'SELECT ... INTO new_table'");
303: // use the generic SqlCommand implementation for this and not the SelectCommand
304: cmd = this .cmdDispatch.get("*");
305: } else {
306: cmd = this .cmdDispatch.get(verb);
307: }
308:
309: if (cmd == null) {
310: cmd = this .cmdDispatch.get("*");
311: }
312: return cmd;
313: }
314:
315: }
|