001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap4j/MondrianOlap4jStatement.java#1 $
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/src/main/mondrian/olap4j/MondrianOlap4jStatement.java#1 $
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