001: /*
002: * StatementContext.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.gui.completion;
013:
014: import java.util.ArrayList;
015: import java.util.Collections;
016: import java.util.HashSet;
017: import java.util.List;
018: import java.util.Set;
019: import workbench.db.WbConnection;
020: import workbench.log.LogMgr;
021: import workbench.sql.formatter.SQLLexer;
022: import workbench.sql.formatter.SQLToken;
023: import workbench.sql.wbcommands.CommandTester;
024: import workbench.sql.wbcommands.WbSelectBlob;
025: import workbench.util.SqlUtil;
026:
027: /**
028: * A factory to generate a BaseAnalyzer based on a given SQL statement
029: * @author support@sql-workbench.net
030: */
031: public class StatementContext {
032: private BaseAnalyzer analyzer;
033: private CommandTester wbTester = new CommandTester();
034:
035: public StatementContext(WbConnection conn, String sql, int pos) {
036: String verb = SqlUtil.getSqlVerb(sql);
037:
038: BaseAnalyzer subSelectAnalyzer = checkSubselect(conn, sql, pos);
039: BaseAnalyzer verbAnalyzer = null;
040:
041: if ("SELECT".equalsIgnoreCase(verb)
042: || WbSelectBlob.VERB.equalsIgnoreCase(verb)) {
043: verbAnalyzer = new SelectAnalyzer(conn, sql, pos);
044: } else if ("UPDATE".equalsIgnoreCase(verb)) {
045: verbAnalyzer = new UpdateAnalyzer(conn, sql, pos);
046: } else if ("DELETE".equalsIgnoreCase(verb)) {
047: verbAnalyzer = new DeleteAnalyzer(conn, sql, pos);
048: } else if ("DROP".equalsIgnoreCase(verb)
049: || "TRUNCATE".equalsIgnoreCase(verb)) {
050: verbAnalyzer = new DdlAnalyzer(conn, sql, pos);
051: } else if ("ALTER".equalsIgnoreCase(verb)) {
052: verbAnalyzer = new AlterTableAnalyzer(conn, sql, pos);
053: } else if ("INSERT".equalsIgnoreCase(verb)) {
054: verbAnalyzer = new InsertAnalyzer(conn, sql, pos);
055: } else if ("CREATE".equalsIgnoreCase(verb)
056: || "CREATE OR REPLACE".equalsIgnoreCase(verb)) {
057: verbAnalyzer = new CreateAnalyzer(conn, sql, pos);
058: } else if (wbTester.isWbCommand(verb)) {
059: verbAnalyzer = new WbCommandAnalyzer(conn, sql, pos);
060: }
061:
062: if (subSelectAnalyzer != null) {
063: this .analyzer = subSelectAnalyzer;
064: this .analyzer.setParent(verbAnalyzer);
065: } else if (verbAnalyzer != null) {
066: this .analyzer = verbAnalyzer;
067: this .analyzer.setParent(null);
068: }
069:
070: if (analyzer != null) {
071: analyzer.retrieveObjects();
072: }
073: }
074:
075: public BaseAnalyzer getAnalyzer() {
076: return this .analyzer;
077: }
078:
079: private BaseAnalyzer checkSubselect(WbConnection conn, String sql,
080: int pos) {
081: try {
082: SQLLexer lexer = new SQLLexer(sql);
083:
084: SQLToken t = lexer.getNextToken(false, false);
085: SQLToken lastToken = null;
086:
087: int lastStart = 0;
088: int lastEnd = 0;
089: String verb = t.getContents();
090:
091: // Will contain the position of each SELECT verb
092: // if a UNION is encountered.
093: List<Integer> unionStarts = new ArrayList<Integer>();
094: int bracketCount = 0;
095: boolean inSubselect = false;
096: boolean checkForInsertSelect = verb.equals("INSERT")
097: || verb.equals("CREATE")
098: || verb.equals("CREATE OR REPLACE");
099:
100: Set<String> unionKeywords = new HashSet<String>();
101: unionKeywords.add("UNION");
102: unionKeywords.add("MINUS");
103: unionKeywords.add("INTERSECT");
104:
105: while (t != null) {
106: final String value = t.getContents();
107:
108: if ("(".equals(value)) {
109: bracketCount++;
110: if (bracketCount == 1)
111: lastStart = t.getCharBegin();
112: } else if (")".equals(value)) {
113: bracketCount--;
114: if (inSubselect && bracketCount == 0) {
115: lastEnd = t.getCharBegin();
116: if (lastStart <= pos && pos <= lastEnd) {
117: int newpos = pos - lastStart - 1;
118: String sub = sql.substring(lastStart + 1,
119: lastEnd);
120: return new SelectAnalyzer(conn, sub, newpos);
121: }
122: }
123: if (bracketCount == 0) {
124: inSubselect = false;
125: lastStart = 0;
126: lastEnd = 0;
127: }
128: } else if (bracketCount == 0 && checkForInsertSelect
129: && value.equals("SELECT")) {
130: if (pos >= t.getCharBegin()) {
131: int newPos = pos - t.getCharBegin();
132: return new SelectAnalyzer(conn, sql.substring(t
133: .getCharBegin()), newPos);
134: }
135: } else if (bracketCount == 0
136: && unionKeywords.contains(value)) {
137: if (value.equals("UNION")) {
138: SQLToken t2 = lexer.getNextToken(false, false);
139: if (t2.getContents().equals("ALL")) {
140: // swallow potential UNION ALL
141: unionStarts.add(new Integer(t
142: .getCharBegin()));
143: } else {
144: unionStarts
145: .add(new Integer(t.getCharEnd()));
146:
147: // continue with the token just read
148: lastToken = t;
149: t = t2;
150: continue;
151: }
152: } else {
153: unionStarts.add(new Integer(t.getCharEnd()));
154: }
155: }
156:
157: if (bracketCount == 1
158: && lastToken.getContents().equals("(")
159: && value.equals("SELECT")) {
160: inSubselect = true;
161: }
162:
163: lastToken = t;
164: t = lexer.getNextToken(false, false);
165: }
166:
167: if (unionStarts.size() > 0) {
168: boolean found = false;
169: int index = 0;
170: int lastPos = 0;
171: while (index < unionStarts.size()) {
172: int startPos = (unionStarts.get(index)).intValue();
173: if (lastPos <= pos && pos <= startPos) {
174: int newPos = pos - lastPos;
175: return new SelectAnalyzer(conn, sql.substring(
176: lastPos, startPos), newPos);
177: }
178: lastPos = startPos;
179: index++;
180: }
181: // check last union
182: int startPos = (unionStarts.get(unionStarts.size() - 1))
183: .intValue();
184: if (pos >= startPos) {
185: int newPos = pos - startPos;
186: return new SelectAnalyzer(conn, sql
187: .substring(startPos), newPos);
188: }
189: }
190: } catch (Exception e) {
191: LogMgr.logError("StatementContenxt.inSubSelect()",
192: "Error when checking sub-select", e);
193: }
194:
195: return null;
196: }
197:
198: public boolean isStatementSupported() {
199: return this .analyzer != null;
200: }
201:
202: public List getData() {
203: if (analyzer == null)
204: return Collections.EMPTY_LIST;
205: List result = analyzer.getData();
206: if (result == null)
207: return Collections.EMPTY_LIST;
208: return result;
209: }
210:
211: public String getTitle() {
212: if (analyzer == null)
213: return "";
214: return analyzer.getTitle();
215: }
216:
217: }
|