001 /*
002 // $Id: //open/mondrian-release/3.0/src/main/mondrian/olap4j/MondrianOlap4jStatement.java#2 $
003 // This software is subject to the terms of the Common Public License
004 // Agreement, available at the following URL:
005 // http://www.opensource.org/licenses/cpl.html.
006 // Copyright (C) 2007-2007 Julian Hyde
007 // All Rights Reserved.
008 // You must accept the terms of that agreement to use this software.
009 */
010 package mondrian.olap4j;
011
012 import mondrian.olap.*;
013 import org.olap4j.*;
014 import org.olap4j.mdx.*;
015
016 import java.io.PrintWriter;
017 import java.io.StringWriter;
018 import java.sql.*;
019 import java.sql.Connection;
020
021 /**
022 * Implementation of {@link org.olap4j.OlapStatement}
023 * for the Mondrian OLAP engine.
024 *
025 * @author jhyde
026 * @version $Id: //open/mondrian-release/3.0/src/main/mondrian/olap4j/MondrianOlap4jStatement.java#2 $
027 * @since May 24, 2007
028 */
029 class MondrianOlap4jStatement implements OlapStatement {
030 final MondrianOlap4jConnection olap4jConnection;
031 private boolean closed;
032
033 /**
034 * Current cell set, or null if the statement is not executing anything.
035 * Any method which modifies this member must synchronize
036 * on the MondrianOlap4jStatement.
037 */
038 MondrianOlap4jCellSet openCellSet;
039 int timeoutSeconds;
040
041 MondrianOlap4jStatement(
042 MondrianOlap4jConnection olap4jConnection)
043 {
044 assert olap4jConnection != null;
045 this.olap4jConnection = olap4jConnection;
046 this.closed = false;
047 }
048
049 // implement Statement
050
051 public ResultSet executeQuery(String sql) throws SQLException {
052 throw new UnsupportedOperationException();
053 }
054
055 private void checkOpen() throws SQLException {
056 if (closed) {
057 throw olap4jConnection.helper.createException("closed");
058 }
059 }
060
061 public int executeUpdate(String sql) throws SQLException {
062 throw new UnsupportedOperationException();
063 }
064
065 public synchronized void close() throws SQLException {
066 if (!closed) {
067 closed = true;
068 if (openCellSet != null) {
069 CellSet c = openCellSet;
070 openCellSet = null;
071 c.close();
072 }
073 }
074 }
075
076 public int getMaxFieldSize() throws SQLException {
077 throw new UnsupportedOperationException();
078 }
079
080 public void setMaxFieldSize(int max) throws SQLException {
081 throw new UnsupportedOperationException();
082 }
083
084 public int getMaxRows() throws SQLException {
085 throw new UnsupportedOperationException();
086 }
087
088 public void setMaxRows(int max) throws SQLException {
089 throw new UnsupportedOperationException();
090 }
091
092 public void setEscapeProcessing(boolean enable) throws SQLException {
093 throw new UnsupportedOperationException();
094 }
095
096 public int getQueryTimeout() throws SQLException {
097 return timeoutSeconds;
098 }
099
100 public void setQueryTimeout(int seconds) throws SQLException {
101 if (seconds < 0) {
102 throw olap4jConnection.helper.createException(
103 "illegal timeout value " + seconds);
104 }
105 this.timeoutSeconds = seconds;
106 }
107
108 public synchronized void cancel() throws SQLException {
109 if (openCellSet != null) {
110 openCellSet.query.cancel();
111 }
112 }
113
114 public SQLWarning getWarnings() throws SQLException {
115 throw new UnsupportedOperationException();
116 }
117
118 public void clearWarnings() throws SQLException {
119 throw new UnsupportedOperationException();
120 }
121
122 public void setCursorName(String name) throws SQLException {
123 throw new UnsupportedOperationException();
124 }
125
126 public boolean execute(String sql) throws SQLException {
127 throw new UnsupportedOperationException();
128 }
129
130 public ResultSet getResultSet() throws SQLException {
131 throw new UnsupportedOperationException();
132 }
133
134 public int getUpdateCount() throws SQLException {
135 throw new UnsupportedOperationException();
136 }
137
138 public boolean getMoreResults() throws SQLException {
139 throw new UnsupportedOperationException();
140 }
141
142 public void setFetchDirection(int direction) throws SQLException {
143 throw new UnsupportedOperationException();
144 }
145
146 public int getFetchDirection() throws SQLException {
147 throw new UnsupportedOperationException();
148 }
149
150 public void setFetchSize(int rows) throws SQLException {
151 throw new UnsupportedOperationException();
152 }
153
154 public int getFetchSize() throws SQLException {
155 throw new UnsupportedOperationException();
156 }
157
158 public int getResultSetConcurrency() throws SQLException {
159 throw new UnsupportedOperationException();
160 }
161
162 public int getResultSetType() throws SQLException {
163 throw new UnsupportedOperationException();
164 }
165
166 public void addBatch(String sql) throws SQLException {
167 throw new UnsupportedOperationException();
168 }
169
170 public void clearBatch() throws SQLException {
171 throw new UnsupportedOperationException();
172 }
173
174 public int[] executeBatch() throws SQLException {
175 throw new UnsupportedOperationException();
176 }
177
178 public Connection getConnection() throws SQLException {
179 throw new UnsupportedOperationException();
180 }
181
182 public boolean getMoreResults(int current) throws SQLException {
183 throw new UnsupportedOperationException();
184 }
185
186 public ResultSet getGeneratedKeys() throws SQLException {
187 throw new UnsupportedOperationException();
188 }
189
190 public int executeUpdate(
191 String sql, int autoGeneratedKeys) throws SQLException {
192 throw new UnsupportedOperationException();
193 }
194
195 public int executeUpdate(
196 String sql, int columnIndexes[]) throws SQLException {
197 throw new UnsupportedOperationException();
198 }
199
200 public int executeUpdate(
201 String sql, String columnNames[]) throws SQLException {
202 throw new UnsupportedOperationException();
203 }
204
205 public boolean execute(
206 String sql, int autoGeneratedKeys) throws SQLException {
207 throw new UnsupportedOperationException();
208 }
209
210 public boolean execute(
211 String sql, int columnIndexes[]) throws SQLException {
212 throw new UnsupportedOperationException();
213 }
214
215 public boolean execute(
216 String sql, String columnNames[]) throws SQLException {
217 throw new UnsupportedOperationException();
218 }
219
220 public int getResultSetHoldability() throws SQLException {
221 throw new UnsupportedOperationException();
222 }
223
224 public boolean isClosed() throws SQLException {
225 return closed;
226 }
227
228 public void setPoolable(boolean poolable) throws SQLException {
229 throw new UnsupportedOperationException();
230 }
231
232 public boolean isPoolable() throws SQLException {
233 throw new UnsupportedOperationException();
234 }
235
236 // implement Wrapper
237
238 public <T> T unwrap(Class<T> iface) throws SQLException {
239 if (iface.isInstance(this)) {
240 return iface.cast(this);
241 }
242 throw olap4jConnection.helper.createException(
243 "does not implement '" + iface + "'");
244 }
245
246 public boolean isWrapperFor(Class<?> iface) throws SQLException {
247 return iface.isInstance(this);
248 }
249
250 // implement OlapStatement
251
252 public CellSet executeOlapQuery(String mdx) throws OlapException {
253 Query query;
254 try {
255 query = olap4jConnection.connection.parseQuery(mdx);
256 } catch (MondrianException e) {
257 throw olap4jConnection.helper.createException(
258 "mondrian gave exception while parsing query", e);
259 }
260 return executeOlapQueryInternal(query);
261 }
262
263 /**
264 * Executes a parsed query, closing any previously open cellset.
265 *
266 * @param query Parsed query
267 * @return Cell set
268 * @throws OlapException if a database error occurs
269 */
270 protected CellSet executeOlapQueryInternal(
271 Query query) throws OlapException
272 {
273 // Close the previous open CellSet, if there is one.
274 synchronized (this) {
275 if (openCellSet != null) {
276 final MondrianOlap4jCellSet cs = openCellSet;
277 openCellSet = null;
278 try {
279 cs.close();
280 } catch (SQLException e) {
281 throw olap4jConnection.helper.createException(
282 null, "Error while closing previous CellSet", e);
283 }
284 }
285
286 openCellSet = olap4jConnection.factory.newCellSet(this, query);
287 }
288 // Release the monitor before executing, to give another thread the
289 // opportunity to call cancel.
290 try {
291 openCellSet.execute();
292 } catch (QueryCanceledException e) {
293 throw olap4jConnection.helper.createException("Query canceled");
294 } catch (QueryTimeoutException e) {
295 throw olap4jConnection.helper.createException(e.getMessage());
296 }
297 return openCellSet;
298 }
299
300 public CellSet executeOlapQuery(SelectNode selectNode) throws OlapException {
301 final String mdx = toString(selectNode);
302 return executeOlapQuery(mdx);
303 }
304
305 /**
306 * Converts a {@link org.olap4j.mdx.ParseTreeNode} to MDX string.
307 *
308 * @param node Parse tree node
309 * @return MDX text
310 */
311 private static String toString(ParseTreeNode node) {
312 StringWriter sw = new StringWriter();
313 PrintWriter pw = new PrintWriter(sw);
314 ParseTreeWriter parseTreeWriter = new ParseTreeWriter(pw);
315 node.unparse(parseTreeWriter);
316 pw.flush();
317 return sw.toString();
318 }
319 }
320
321 // End MondrianOlap4jStatement.java