001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap4j/MondrianOlap4jPreparedStatement.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 org.olap4j.*;
013    import org.olap4j.type.*;
014    import org.olap4j.metadata.*;
015    
016    import java.sql.*;
017    import java.math.BigDecimal;
018    import java.io.InputStream;
019    import java.io.Reader;
020    import java.util.Calendar;
021    import java.net.URL;
022    
023    import mondrian.olap.Query;
024    import mondrian.olap.Parameter;
025    
026    /**
027     * Implementation of {@link PreparedOlapStatement}
028     * for the Mondrian OLAP engine.
029     *
030     * <p>This class has sub-classes which implement JDBC 3.0 and JDBC 4.0 APIs;
031     * it is instantiated using {@link Factory#newPreparedStatement}.</p>
032     *
033     * @author jhyde
034     * @version $Id: //open/mondrian/src/main/mondrian/olap4j/MondrianOlap4jPreparedStatement.java#1 $
035     * @since Jun 12, 2007
036     */
037    abstract class MondrianOlap4jPreparedStatement
038        extends MondrianOlap4jStatement
039        implements PreparedOlapStatement, OlapParameterMetaData
040    {
041        private final String mdx;
042        private Query query;
043        MondrianOlap4jCellSetMetaData cellSetMetaData;
044    
045        public MondrianOlap4jPreparedStatement(
046            MondrianOlap4jConnection olap4jConnection,
047            String mdx)
048        {
049            super(olap4jConnection);
050            this.mdx = mdx;
051            this.query = olap4jConnection.connection.parseQuery(mdx);
052            this.cellSetMetaData = new MondrianOlap4jCellSetMetaData(this, query);
053        }
054    
055        // override OlapStatement
056    
057        public CellSet executeOlapQuery(String mdx) throws OlapException {
058            this.query = olap4jConnection.connection.parseQuery(mdx);
059            this.cellSetMetaData = new MondrianOlap4jCellSetMetaData(this, query);
060            return executeOlapQueryInternal(query);
061        }
062    
063        // implement PreparedOlapStatement
064    
065        public CellSet executeQuery() throws OlapException {
066            return executeOlapQueryInternal(query);
067        }
068    
069        public OlapParameterMetaData getParameterMetaData() throws OlapException {
070            return this;
071        }
072    
073        public Cube getCube() {
074            throw new UnsupportedOperationException();
075        }
076    
077        // implement PreparedStatement
078    
079        public int executeUpdate() throws SQLException {
080            throw new UnsupportedOperationException();
081        }
082    
083        public void setNull(int parameterIndex, int sqlType) throws SQLException {
084            getParameter(parameterIndex).setValue(null);
085        }
086    
087        public void setBoolean(int parameterIndex, boolean x) throws SQLException {
088            getParameter(parameterIndex).setValue(x);
089        }
090    
091        public void setByte(int parameterIndex, byte x) throws SQLException {
092            getParameter(parameterIndex).setValue(x);
093        }
094    
095        public void setShort(int parameterIndex, short x) throws SQLException {
096            getParameter(parameterIndex).setValue(x);
097        }
098    
099        public void setInt(int parameterIndex, int x) throws SQLException {
100            getParameter(parameterIndex).setValue(x);
101        }
102    
103        public void setLong(int parameterIndex, long x) throws SQLException {
104            getParameter(parameterIndex).setValue(x);
105        }
106    
107        public void setFloat(int parameterIndex, float x) throws SQLException {
108            getParameter(parameterIndex).setValue(x);
109        }
110    
111        public void setDouble(int parameterIndex, double x) throws SQLException {
112            getParameter(parameterIndex).setValue(x);
113        }
114    
115        public void setBigDecimal(
116            int parameterIndex, BigDecimal x) throws SQLException {
117            getParameter(parameterIndex).setValue(x);
118        }
119    
120        public void setString(int parameterIndex, String x) throws SQLException {
121            getParameter(parameterIndex).setValue(x);
122        }
123    
124        public void setBytes(int parameterIndex, byte x[]) throws SQLException {
125            getParameter(parameterIndex).setValue(x);
126        }
127    
128        public void setDate(int parameterIndex, Date x) throws SQLException {
129            getParameter(parameterIndex).setValue(x);
130        }
131    
132        public void setTime(int parameterIndex, Time x) throws SQLException {
133            getParameter(parameterIndex).setValue(x);
134        }
135    
136        public void setTimestamp(
137            int parameterIndex, Timestamp x) throws SQLException {
138            getParameter(parameterIndex).setValue(x);
139        }
140    
141        public void setAsciiStream(
142            int parameterIndex, InputStream x, int length) throws SQLException {
143            getParameter(parameterIndex).setValue(x);
144        }
145    
146        public void setUnicodeStream(
147            int parameterIndex, InputStream x, int length) throws SQLException {
148            getParameter(parameterIndex).setValue(x);
149        }
150    
151        public void setBinaryStream(
152            int parameterIndex, InputStream x, int length) throws SQLException {
153            getParameter(parameterIndex).setValue(x);
154        }
155    
156        public void clearParameters() throws SQLException {
157            throw new UnsupportedOperationException();
158        }
159    
160        public void setObject(
161            int parameterIndex, Object x, int targetSqlType) throws SQLException {
162            getParameter(parameterIndex).setValue(x);
163        }
164    
165        public void setObject(int parameterIndex, Object x) throws SQLException {
166            final Parameter parameter = getParameter(parameterIndex);
167            if (x instanceof MondrianOlap4jMember) {
168                MondrianOlap4jMember mondrianOlap4jMember =
169                    (MondrianOlap4jMember) x;
170                x = mondrianOlap4jMember.member;
171            }
172            parameter.setValue(x);
173        }
174    
175        public boolean execute() throws SQLException {
176            throw new UnsupportedOperationException();
177        }
178    
179        public void addBatch() throws SQLException {
180            throw new UnsupportedOperationException();
181        }
182    
183        public void setCharacterStream(
184            int parameterIndex, Reader reader, int length) throws SQLException {
185            throw new UnsupportedOperationException();
186        }
187    
188        public void setRef(int parameterIndex, Ref x) throws SQLException {
189            throw new UnsupportedOperationException();
190        }
191    
192        public void setBlob(int parameterIndex, Blob x) throws SQLException {
193            throw new UnsupportedOperationException();
194        }
195    
196        public void setClob(int parameterIndex, Clob x) throws SQLException {
197            throw new UnsupportedOperationException();
198        }
199    
200        public void setArray(int parameterIndex, Array x) throws SQLException {
201            throw new UnsupportedOperationException();
202        }
203    
204        public CellSetMetaData getMetaData() {
205            return cellSetMetaData;
206        }
207    
208        public void setDate(
209            int parameterIndex, Date x, Calendar cal) throws SQLException {
210            throw new UnsupportedOperationException();
211        }
212    
213        public void setTime(
214            int parameterIndex, Time x, Calendar cal) throws SQLException {
215            throw new UnsupportedOperationException();
216        }
217    
218        public void setTimestamp(
219            int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
220            throw new UnsupportedOperationException();
221        }
222    
223        public void setNull(
224            int parameterIndex, int sqlType, String typeName) throws SQLException {
225            throw new UnsupportedOperationException();
226        }
227    
228        public void setURL(int parameterIndex, URL x) throws SQLException {
229            throw new UnsupportedOperationException();
230        }
231    
232        public void setObject(
233            int parameterIndex,
234            Object x,
235            int targetSqlType,
236            int scaleOrLength) throws SQLException {
237            throw new UnsupportedOperationException();
238        }
239    
240        // implement OlapParameterMetaData
241    
242        public String getParameterName(int param) throws OlapException {
243            Parameter paramDef = getParameter(param);
244            return paramDef.getName();
245        }
246    
247        private Parameter getParameter(int param) throws OlapException {
248            final Parameter[] parameters = query.getParameters();
249            if (param < 1 || param > parameters.length) {
250                throw this.olap4jConnection.helper.toOlapException(
251                    this.olap4jConnection.helper.createException(
252                        "parameter ordinal " + param + " out of range"));
253            }
254            return parameters[param - 1];
255        }
256    
257        public Type getParameterOlapType(int param) throws OlapException {
258            Parameter paramDef = getParameter(param);
259            return olap4jConnection.toOlap4j(paramDef.getType());
260        }
261    
262        public int getParameterCount() {
263            return query.getParameters().length;
264        }
265    
266        public int isNullable(int param) throws SQLException {
267            return ParameterMetaData.parameterNullableUnknown;
268        }
269    
270        public boolean isSigned(int param) throws SQLException {
271            final Type type = getParameterOlapType(param);
272            return type instanceof NumericType;
273        }
274    
275        public int getPrecision(int param) throws SQLException {
276            final Type type = getParameterOlapType(param);
277            if (type instanceof NumericType) {
278                return 0; // precision not applicable
279            }
280            if (type instanceof StringType) {
281                return Integer.MAX_VALUE;
282            }
283            return 0;
284        }
285    
286        public int getScale(int param) throws SQLException {
287            return 0; // scale not applicable
288        }
289    
290        public int getParameterType(int param) throws SQLException {
291            final Type type = getParameterOlapType(param);
292            if (type instanceof NumericType) {
293                return Types.NUMERIC;
294            } else if (type instanceof StringType) {
295                return Types.VARCHAR;
296            } else if (type instanceof NullType) {
297                return Types.NULL;
298            } else {
299                return Types.OTHER;
300            }
301        }
302    
303        public String getParameterTypeName(int param) throws SQLException {
304            final Type type = getParameterOlapType(param);
305            return type.toString();
306        }
307    
308        public String getParameterClassName(int param) throws SQLException {
309            final Type type = getParameterOlapType(param);
310            return foo(
311                new TypeHelper<Class>() {
312                    public Class booleanType(BooleanType type) {
313                        return Boolean.class;
314                    }
315    
316                    public Class<Cube> cubeType(CubeType cubeType) {
317                        return Cube.class;
318                    }
319    
320                    public Class<Number> decimalType(DecimalType decimalType) {
321                        return Number.class;
322                    }
323    
324                    public Class<Dimension> dimensionType(DimensionType dimensionType) {
325                        return Dimension.class;
326                    }
327    
328                    public Class<Hierarchy> hierarchyType(HierarchyType hierarchyType) {
329                        return Hierarchy.class;
330                    }
331    
332                    public Class<Level> levelType(LevelType levelType) {
333                        return Level.class;
334                    }
335    
336                    public Class<Member> memberType(MemberType memberType) {
337                        return Member.class;
338                    }
339    
340                    public Class<Void> nullType(NullType nullType) {
341                        return Void.class;
342                    }
343    
344                    public Class<Number> numericType(NumericType numericType) {
345                        return Number.class;
346                    }
347    
348                    public Class<Iterable> setType(SetType setType) {
349                        return Iterable.class;
350                    }
351    
352                    public Class<String> stringType(StringType stringType) {
353                        return String.class;
354                    }
355    
356                    public Class<Member[]> tupleType(TupleType tupleType) {
357                        return Member[].class;
358                    }
359    
360                    public Class symbolType(SymbolType symbolType) {
361                        // parameters cannot be of this type
362                        throw new UnsupportedOperationException();
363                    }
364                },
365                type).getName();
366        }
367    
368        public int getParameterMode(int param) throws SQLException {
369            Parameter paramDef = getParameter(param); // forces param range check
370            return ParameterMetaData.parameterModeIn;
371        }
372    
373        // Helper classes
374    
375        private interface TypeHelper<T> {
376            T booleanType(BooleanType type);
377            T cubeType(CubeType cubeType);
378            T decimalType(DecimalType decimalType);
379            T dimensionType(DimensionType dimensionType);
380            T hierarchyType(HierarchyType hierarchyType);
381            T levelType(LevelType levelType);
382            T memberType(MemberType memberType);
383            T nullType(NullType nullType);
384            T numericType(NumericType numericType);
385            T setType(SetType setType);
386            T stringType(StringType stringType);
387            T tupleType(TupleType tupleType);
388            T symbolType(SymbolType symbolType);
389        }
390    
391        <T> T foo(TypeHelper<T> helper, Type type) {
392            if (type instanceof BooleanType) {
393                return helper.booleanType((BooleanType) type);
394            } else if (type instanceof CubeType) {
395                return helper.cubeType((CubeType) type);
396            } else if (type instanceof DecimalType) {
397                return helper.decimalType((DecimalType) type);
398            } else if (type instanceof DimensionType) {
399                return helper.dimensionType((DimensionType) type);
400            } else if (type instanceof HierarchyType) {
401                return helper.hierarchyType((HierarchyType) type);
402            } else if (type instanceof LevelType) {
403                return helper.levelType((LevelType) type);
404            } else if (type instanceof MemberType) {
405                return helper.memberType((MemberType) type);
406            } else if (type instanceof NullType) {
407                return helper.nullType((NullType) type);
408            } else if (type instanceof NumericType) {
409                return helper.numericType((NumericType) type);
410            } else if (type instanceof SetType) {
411                return helper.setType((SetType) type);
412            } else if (type instanceof StringType) {
413                return helper.stringType((StringType) type);
414            } else if (type instanceof TupleType) {
415                return helper.tupleType((TupleType) type);
416            } else if (type instanceof SymbolType) {
417                return helper.symbolType((SymbolType) type);
418            } else {
419                throw new UnsupportedOperationException();
420            }
421        }
422    }
423    
424    // End MondrianOlap4jPreparedStatement.java