1 23 24 package org.objectweb.medor.datasource.rdb.lib; 25 26 import org.objectweb.jorm.mapper.rdb.adapter.api.RdbAdapter; 27 import org.objectweb.jorm.mapper.rdb.adapter.BasicRdbAdapter; 28 import org.objectweb.jorm.mapper.rdb.adapter.OracleAdapter; 29 import org.objectweb.jorm.mapper.rdb.lib.RdbConnectionWrapper; 30 import org.objectweb.jorm.api.PException; 31 import org.objectweb.medor.api.EvaluationException; 32 import org.objectweb.medor.api.MedorException; 33 import org.objectweb.medor.datasource.api.Wrapper; 34 import org.objectweb.medor.expression.api.CalculatedParameterOperand; 35 import org.objectweb.medor.expression.api.Operator; 36 import org.objectweb.medor.expression.api.ParameterOperand; 37 import org.objectweb.medor.expression.api.Expression; 38 import org.objectweb.medor.expression.api.Operand; 39 import org.objectweb.medor.expression.api.ExpressionException; 40 import org.objectweb.medor.expression.lib.BasicParameterOperand; 41 import org.objectweb.medor.filter.lib.InCollection; 42 import org.objectweb.medor.lib.Log; 43 import org.objectweb.medor.query.api.FilteredQueryTree; 44 import org.objectweb.medor.query.api.QueryLeaf; 45 import org.objectweb.medor.query.api.QueryTree; 46 import org.objectweb.medor.query.rdb.api.RdbExpQueryLeaf; 47 import org.objectweb.medor.query.rdb.api.RdbQueryLeaf; 48 import org.objectweb.medor.query.rdb.lib.AggregateRdbQueryNode; 49 import org.objectweb.medor.tuple.api.TupleCollection; 50 import org.objectweb.medor.tuple.lib.EmptyTupleCollection; 51 import org.objectweb.medor.type.lib.PTypeSpaceMedor; 52 import org.objectweb.medor.type.lib.QTypeTuple; 53 import org.objectweb.medor.eval.api.EvaluationMetaData; 54 import org.objectweb.util.monolog.api.BasicLevel; 55 import org.objectweb.util.monolog.api.Logger; 56 57 import java.io.Serializable ; 58 import java.io.IOException ; 59 import java.math.BigDecimal ; 60 import java.sql.Connection ; 61 import java.sql.PreparedStatement ; 62 import java.sql.ResultSet ; 63 import java.sql.SQLException ; 64 import java.util.ArrayList ; 65 import java.util.Date ; 66 import java.util.Collection ; 67 import java.util.Iterator ; 68 69 75 public class JDBCWrapper implements Wrapper { 76 77 80 static Logger log = null; 81 static Logger TClog = null; 82 boolean debug; 83 84 public JDBCWrapper() { 85 if (log == null) { 86 log = Log.loggerFactory.getLogger( 87 Log.MEDOR_PREFIX + ".eval.rdb.JDBCWrapper"); 88 TClog = Log.loggerFactory.getLogger( 89 Log.MEDOR_PREFIX + ".eval.rdb.JDBCTC"); 90 } 91 } 92 93 public TupleCollection fetchData(QueryLeaf lf, 94 ParameterOperand[] parameters, 95 Object connection, 96 EvaluationMetaData evalMD) 97 throws EvaluationException { 98 debug = log.isLoggable(BasicLevel.DEBUG); 99 if (debug) { 100 log.log(BasicLevel.DEBUG, "Parameters: " + posToString(parameters)); 101 } 102 RdbQueryLeaf leaf = (RdbQueryLeaf) lf; 103 ParameterOperand[] usedParameters = null; 104 RdbAdapter rdbAdapt = getRdbAdapter(leaf); 106 Connection conn = getConnection(connection); 107 ResultSet resultSet = null; 108 PreparedStatement ps = null; 109 String sqlRequest; 110 synchronized (leaf) { 111 if (parameters != null 112 && parameters.length > 0 113 && leaf instanceof FilteredQueryTree) { 114 Expression filter = ((FilteredQueryTree) leaf).getQueryFilter(); 115 if (filter != null) { 116 ArrayList al = getUsedParameters(filter, parameters, null); 117 al = addRangeParameters(al, rdbAdapt, evalMD); 119 if (al != null && al.size() > 0) { 120 usedParameters = (ParameterOperand[]) 121 al.toArray(new ParameterOperand[al.size()]); 122 } 123 } 124 } 125 if (debug) { 126 log.log(BasicLevel.DEBUG, "Used parameters: " + posToString(parameters)); 127 } 128 try { 129 sqlRequest = leaf.getSqlRequest(usedParameters, 131 (evalMD != null && evalMD.getLimitedRangeStartAt() > 0), 132 (evalMD != null && evalMD.getLimitedRangeSize() < Integer.MAX_VALUE)); 133 if (debug) { 134 log.log(BasicLevel.DEBUG, "SQL query for leaf " + leaf + ": " + sqlRequest); 135 } 136 ps = conn.prepareStatement( 137 sqlRequest, 138 ResultSet.TYPE_SCROLL_INSENSITIVE, 139 ResultSet.CONCUR_READ_ONLY); 140 if (usedParameters != null) { 141 assignParameter(ps, usedParameters, rdbAdapt); 142 } 143 } catch (Exception e) { 144 throw new EvaluationException(e); 145 } 146 } 147 if (debug) { 148 log.log(BasicLevel.DEBUG, "Evaluate the query: " + sqlRequest); 149 } 150 try { 151 resultSet = ps.executeQuery(); 152 if (!resultSet.next()) { 153 if (debug) log.log(BasicLevel.DEBUG, "No result, closing the ResultSet and the PreparedStatement"); 154 resultSet.close(); 155 ps.close(); 156 return new EmptyTupleCollection(lf.getTupleStructure()); 157 } else { 158 if (debug) log.log(BasicLevel.DEBUG, "There is a result"); 159 return new JDBCTupleCollection( 160 lf.getTupleStructure(), resultSet, ps, rdbAdapt, TClog); 161 } 162 } catch (EvaluationException ee) { 163 throw ee; 164 } catch (Exception mexp) { 165 throw new EvaluationException(mexp); 166 } 167 } 168 169 private Connection getConnection(Object connection) throws EvaluationException { 170 try { 171 return RdbConnectionWrapper.narrow2SQL(connection); 172 } catch (PException e) { 173 throw new EvaluationException( 174 "Impossible to evaluate a jdbc leaf:", e); 175 } 176 } 177 178 private RdbAdapter getRdbAdapter(RdbQueryLeaf leaf) { 179 RdbAdapter rdbAdapt = null; 180 if (leaf instanceof RdbExpQueryLeaf) { 181 rdbAdapt = ((RdbExpQueryLeaf) leaf).getRdbAdapter(); 182 } else if (leaf instanceof AggregateRdbQueryNode) { 183 QueryTree[] children = ((AggregateRdbQueryNode) leaf).getChildren(); 184 int i=0; 185 while(rdbAdapt == null) { 186 rdbAdapt = getRdbAdapter((RdbQueryLeaf) children[i]); 187 i++; 188 } 189 } 190 if (rdbAdapt == null) { 191 rdbAdapt = new BasicRdbAdapter(); 192 } 193 return rdbAdapt; 194 } 195 196 private void assignParameter(PreparedStatement ps, 197 ParameterOperand[] usedParameters, 198 RdbAdapter rdbAdapt) 199 throws MedorException, ExpressionException, SQLException , IOException { 200 for (int i = 0; i < usedParameters.length; i++) { 201 ParameterOperand po = usedParameters[i]; 202 if (debug) { 203 log.log(BasicLevel.DEBUG, "Assign parameter (name=" 204 + po.getName() + ", value=" + po + ")"); 205 } 206 switch (po.getType().getTypeCode()) { 207 case QTypeTuple.TYPECODE_INT: 208 rdbAdapt.setInt(ps, i + 1, po.getInt()); 209 break; 210 case QTypeTuple.TYPECODE_OBJINT: 211 rdbAdapt.setOint(ps, i + 1, (Integer ) po.getObject()); 212 break; 213 case QTypeTuple.TYPECODE_SHORT: 214 rdbAdapt.setShort(ps, i + 1, po.getShort()); 215 break; 216 case QTypeTuple.TYPECODE_OBJSHORT: 217 rdbAdapt.setOshort(ps, i + 1, (Short ) po.getObject()); 218 break; 219 case QTypeTuple.TYPECODE_BYTE: 220 rdbAdapt.setByte(ps, i + 1, po.getByte()); 221 break; 222 case QTypeTuple.TYPECODE_OBJBYTE: 223 rdbAdapt.setObyte(ps, i + 1, (Byte ) po.getObject()); 224 break; 225 case QTypeTuple.TYPECODE_LONG: 226 rdbAdapt.setLong(ps, i + 1, po.getLong()); 227 break; 228 case QTypeTuple.TYPECODE_OBJLONG: 229 rdbAdapt.setOlong(ps, i + 1, (Long ) po.getObject()); 230 break; 231 case QTypeTuple.TYPECODE_DOUBLE: 232 rdbAdapt.setDouble(ps, i + 1, po.getDouble()); 233 break; 234 case QTypeTuple.TYPECODE_OBJDOUBLE: 235 rdbAdapt.setOdouble(ps, i + 1, (Double ) po.getObject()); 236 break; 237 case QTypeTuple.TYPECODE_BOOLEAN: 238 rdbAdapt.setBoolean(ps, i + 1, po.getBoolean()); 239 break; 240 case QTypeTuple.TYPECODE_OBJBOOLEAN: 241 rdbAdapt.setOboolean(ps, i + 1, (Boolean ) po.getObject()); 242 break; 243 case QTypeTuple.TYPECODE_FLOAT: 244 rdbAdapt.setFloat(ps, i + 1, po.getFloat()); 245 break; 246 case QTypeTuple.TYPECODE_OBJFLOAT: 247 rdbAdapt.setOfloat(ps, i + 1, (Float ) po.getObject()); 248 break; 249 case QTypeTuple.TYPECODE_BIGDECIMAL: 250 case QTypeTuple.TYPECODE_BIGINTEGER: 251 rdbAdapt.setBigDecimal(ps, i + 1, (BigDecimal ) po.getObject()); 252 break; 253 case QTypeTuple.TYPECODE_STRING: 254 rdbAdapt.setString(ps, i + 1, (String ) po.getObject()); 255 break; 256 case QTypeTuple.TYPECODE_CHAR: 257 rdbAdapt.setChar(ps, i + 1, po.getChar()); 258 break; 259 case QTypeTuple.TYPECODE_OBJCHAR: 260 rdbAdapt.setOchar(ps, i + 1, (Character ) po.getObject()); 261 break; 262 case QTypeTuple.TYPECODE_SERIALIZED: 263 rdbAdapt.setSerialized(ps, i + 1, (Serializable ) po.getObject()); 264 break; 265 case QTypeTuple.TYPECODE_DATE: 266 rdbAdapt.setDate(ps, i + 1, (Date ) po.getObject(), null); 267 break; 268 case QTypeTuple.TYPECODE_BYTEARRAY: 269 rdbAdapt.setByteArray(ps, i + 1, (byte[]) po.getObject()); 270 break; 271 case QTypeTuple.TYPECODE_CHARARRAY: 272 rdbAdapt.setCharArray(ps, i + 1, (char[]) po.getObject()); 273 break; 274 case QTypeTuple.TYPECODE_COLLECTION: 275 break; 277 default: 278 throw new EvaluationException("The type " 279 + po.getType().getJormName() 280 + " is not supported '" 281 + po.getType().getTypeCode() + "'" 282 ); 283 } 284 } 285 } 286 287 private ArrayList getUsedParameters(Expression e, 288 ParameterOperand[] parameters, 289 ArrayList al) 290 throws EvaluationException { 291 if ((e instanceof InCollection) && 293 !(((Operator) e).getExpression(1) instanceof ParameterOperand) 294 ) { 295 al = getUsedParameters(((Operator) e).getExpression(0), 296 parameters, al); 297 al = getUsedParametersInCollection( 298 (Collection) ((Operand) ((Operator) e).getExpression(1)).getObject(), 299 parameters, 300 al); 301 } else if (e instanceof Operator) { 302 for (int i = 0; i < ((Operator) e).getOperandNumber(); i++) { 303 al = getUsedParameters(((Operator) e).getExpression(i), 304 parameters, al); 305 } 306 } else if (e instanceof CalculatedParameterOperand) { 307 CalculatedParameterOperand cpo = (CalculatedParameterOperand) e; 308 try { 309 cpo.evaluate(parameters); 310 } catch (ExpressionException e1) { 311 throw new EvaluationException(e1); 312 } 313 if (al == null) 314 al = new ArrayList (); 315 al.add(cpo); 316 } else if (e instanceof ParameterOperand) { 317 int i = 0; 318 ParameterOperand param = (ParameterOperand) e; 319 while (i < parameters.length 320 && !parameters[i].getName().equals(param.getName())) 321 i++; 322 if (i < parameters.length) { 323 if (parameters[i].getType().getTypeCode() != 324 param.getType().getTypeCode()) { 325 throw new EvaluationException("Bad parameter type: found " 326 + parameters[i].getType().getJormName() 327 + " / expected " + param.getType().getJormName()); 328 } 329 if (al == null) 330 al = new ArrayList (); 331 al.add(parameters[i]); 332 } else { 333 StringBuffer msg = new StringBuffer (); 334 msg.append("You must specify the value of parameter "); 335 msg.append(param.getName()); 336 msg.append(". Found: {"); 337 String sep = ""; 338 for (int j = 0; j < parameters.length; j++) { 339 msg.append(sep); 340 msg.append(parameters[j].getName()); 341 sep = ", "; 342 } 343 msg.append("}"); 344 throw new EvaluationException(msg.toString()); 345 } 346 } 347 return al; 348 349 } 350 351 private ArrayList getUsedParametersInCollection( 352 Collection col, 353 ParameterOperand[] parameters, 354 ArrayList al) 355 throws EvaluationException { 356 Iterator colit = col.iterator(); 357 while (colit.hasNext()) { 358 Object e = colit.next(); 359 if (e instanceof ParameterOperand) { 360 int i = 0; 361 ParameterOperand param = (ParameterOperand) e; 362 while (i < parameters.length 363 && !parameters[i].getName().equals(param.getName())) 364 i++; 365 if (i < parameters.length) { 366 if (parameters[i].getType().getTypeCode() != 367 param.getType().getTypeCode()) { 368 throw new EvaluationException("Bad parameter type: found " 369 + parameters[i].getType().getJormName() 370 + " / expected " + param.getType().getJormName()); 371 } 372 if (al == null) 373 al = new ArrayList (); 374 al.add(parameters[i]); 375 } else { 376 String msg = "You must specify the value of parameter " 377 + param.getName() + ". Found: {"; 378 String sep = ""; 379 for (int j = 0; j < parameters.length; j++) { 380 msg += sep + parameters[j].getName(); 381 sep = ", "; 382 } 383 msg += "}"; 384 throw new EvaluationException(msg); 385 } 386 } 387 } 388 return al; 389 } 390 391 private String posToString(ParameterOperand[] pos) { 392 if (pos == null) { 393 return "null"; 394 } 395 StringBuffer sb = new StringBuffer ("["); 396 String sep = ""; 397 for (int i = 0; i < pos.length; i++) { 398 sb.append(sep); 399 sb.append("(name='"); 400 sb.append("'"); 401 sb.append(pos[i].getName()); 402 sb.append("', value="); 403 sb.append(pos[i]); 404 sb.append(")"); 405 } 406 sb.append("]"); 407 return sb.toString(); 408 } 409 410 private ArrayList addRangeParameters(ArrayList al, 411 RdbAdapter rdbAdapt, 412 EvaluationMetaData evalMD) { 413 if (evalMD != null) { 414 int rangePosition = rdbAdapt.getRangeParametersAtStart(); 415 if (rangePosition != RdbAdapter.RANGEUNSUPPORTED) { 416 if (al == null) { 417 al = new ArrayList (); 418 } 419 int rangeStart = evalMD.getLimitedRangeStartAt(); 420 if (rangeStart > 0) { 421 BasicParameterOperand rangeStartParam = 422 new BasicParameterOperand(PTypeSpaceMedor.INT, 423 "rangeStart", 424 rangeStart); 425 if (rangePosition == RdbAdapter.RANGEATSTART) { 427 al.add(0, rangeStartParam); 428 } else { 429 al.add(rangeStartParam); 430 } 431 } 432 433 int rangeSize = evalMD.getLimitedRangeSize(); 434 if (rangeSize < Integer.MAX_VALUE) { 435 ParameterOperand rangeSizeParam = 436 new BasicParameterOperand(PTypeSpaceMedor.INT, 437 "rangeSize", 438 rangeSize); 439 if (rangePosition == RdbAdapter.RANGEATSTART) { 440 if (rangeStart > 0) { 441 al.add(1, rangeSizeParam); 442 } else { al.add(0, rangeSizeParam); 444 } 445 } else { 446 al.add(rangeSizeParam); 447 } 448 if (rangeStart > 0 && rdbAdapt instanceof OracleAdapter) { 449 al.add(new BasicParameterOperand(PTypeSpaceMedor.INT, 450 "rangeStart", 451 rangeStart)); 452 } 453 } 454 } 455 } 456 return al; 457 } 458 } 459 | Popular Tags |