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