1 23 24 package org.objectweb.medor.query.rdb.lib; 25 26 import org.objectweb.jorm.mapper.rdb.adapter.api.JoinedTable; 27 import org.objectweb.jorm.mapper.rdb.adapter.api.RdbAdapter; 28 import org.objectweb.jorm.mapper.rdb.adapter.BasicRdbAdapter; 29 import org.objectweb.jorm.type.api.PType; 30 import org.objectweb.medor.api.MedorException; 31 import org.objectweb.medor.api.QueryLeafException; 32 import org.objectweb.medor.datasource.api.DataStore; 33 import org.objectweb.medor.expression.api.Expression; 34 import org.objectweb.medor.expression.api.ExpressionException; 35 import org.objectweb.medor.expression.api.ParameterOperand; 36 import org.objectweb.medor.filter.api.AggregateOperator; 37 import org.objectweb.medor.filter.api.FieldOperand; 38 import org.objectweb.medor.filter.lib.Count; 39 import org.objectweb.medor.filter.lib.ExpressionPrinter; 40 import org.objectweb.medor.query.api.CalculatedField; 41 import org.objectweb.medor.query.api.OrderField; 42 import org.objectweb.medor.query.api.QueryTreeField; 43 import org.objectweb.medor.query.rdb.api.QualifiedTable; 44 import org.objectweb.medor.query.rdb.api.RdbExpField; 45 import org.objectweb.medor.query.rdb.api.RdbExpQueryLeaf; 46 import org.objectweb.medor.type.lib.QType; 47 import org.objectweb.util.monolog.api.BasicLevel; 48 49 import java.util.ArrayList ; 50 import java.util.List ; 51 import java.util.Map ; 52 53 58 public class BasicRdbExpQueryLeaf extends BasicRdbQueryLeaf implements 59 RdbExpQueryLeaf { 60 61 64 private MedorExpression2WhereClause exp2where; 65 66 private boolean noGroupBy = false; 67 68 QualifiedTable[] from; 69 70 73 private ArrayList groupByFields = new ArrayList (); 74 75 String rdbAdapterName = null; 76 77 RdbAdapter rdbAdapter = null; 78 79 List rootJoinedTables; 80 81 84 boolean canReuseSQL = false; 85 86 public BasicRdbExpQueryLeaf() { 87 } 88 89 public BasicRdbExpQueryLeaf(DataStore ds, String nodeName) { 90 super(nodeName, ds); 91 exp2where = new MedorExpression2WhereClause(); 92 } 93 94 109 public BasicRdbExpQueryLeaf(DataStore ds, QualifiedTable[] from, 110 String nodeName) throws QueryLeafException { 111 this(ds, nodeName); 112 this.from = from; 117 } 118 119 public Object clone(Object clone, Map obj2clone) 120 throws CloneNotSupportedException { 121 clone = super.clone(clone, obj2clone); 122 BasicRdbExpQueryLeaf ql = (BasicRdbExpQueryLeaf) clone; 123 if (from != null) { 124 ql.from = new QualifiedTable[from.length]; 125 for (int i = 0; i < from.length; i++) { 126 ql.from[i] = (QualifiedTable) getClone(from[i], obj2clone); 127 } 128 } 129 if (groupByFields != null) { 130 ql.groupByFields = new ArrayList (); 131 for (int i = 0; i < groupByFields.size(); i++) { 132 RdbExpField gb = (RdbExpField) groupByFields.get(i); 133 if (gb == null) { 134 ql.groupByFields.add(null); 135 } else { 136 ql.groupByFields.add(gb.clone(null, obj2clone)); 137 } 138 } 139 } 140 ql.rdbAdapterName = rdbAdapterName; 141 ql.rdbAdapter = rdbAdapter; 142 ql.exp2where = exp2where; 143 if (rootJoinedTables != null) { 144 ql.rootJoinedTables = new ArrayList (); 145 for (int i = 0; i < rootJoinedTables.size(); i++) { 146 JoinedTable jt = (JoinedTable) rootJoinedTables.get(i); 147 if (jt == null) { 148 ql.rootJoinedTables.add(null); 149 } else { 150 ql.rootJoinedTables.add(jt.clone(null, obj2clone)); 151 } 152 } 153 } 154 return clone; 155 } 156 157 public void setRdbAdapterName(String an) { 158 logger.log(BasicLevel.DEBUG, "Setting rdbAdapterName to " + an); 159 this.rdbAdapterName = an; 160 } 161 162 public String getRdbAdapterName() { 163 return rdbAdapterName; 164 } 165 166 public void setRdbAdapter(RdbAdapter adapter) { 167 logger.log(BasicLevel.DEBUG, "Setting rdbAdapter to " + adapter); 168 rdbAdapter = adapter; 169 } 170 171 public RdbAdapter getRdbAdapter() { 172 return rdbAdapter; 173 } 174 175 public void setRootJoinedTables(List rootjts) { 176 rootJoinedTables = rootjts; 177 } 178 179 192 public RdbExpField addRdbField(String name, PType type, String colName, 193 QualifiedTable table) throws QueryLeafException { 194 QualifiedTable[] qts = this.getQualifiedTables(); 197 int i = 0; 198 while (i < qts.length) { 199 if (table == qts[i]) 200 break; 201 else 202 i++; 203 } 204 if (i == qts.length) 205 throw new QueryLeafException( 206 "The parameter QualifiedTable is not a QualifiedTable of the current RdbExpQueryLeaf"); 207 else { 208 RdbExpField f = new BasicRdbExpField(name, type, colName, table, 209 this); 210 name2field.put(f.getName(), f); 211 fields.add(f); 212 return f; 213 } 214 } 215 216 public void addQualifiedTable(QualifiedTable qt) { 217 if (from == null) 218 from = new QualifiedTable[] { qt }; 219 else { 220 QualifiedTable[] qts = new QualifiedTable[from.length + 1]; 221 System.arraycopy(from, 0, qts, 0, from.length); 222 qts[from.length] = qt; 223 from = qts; 224 } 225 } 226 227 public void removeQualifiedTable(QualifiedTable qt) throws MedorException { 228 if (from == null) 229 throw new MedorException("QualifiedTable " + qt 230 + " is not in leaf " + this); 231 for (int i = 0; i < from.length; i++) { 232 if (from[i] == qt) { 233 if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) { 234 logger.log(BasicLevel.DEBUG, "Found table " 235 + qt.getTableName()); 236 } 237 QualifiedTable[] qts = new QualifiedTable[from.length - 1]; 238 System.arraycopy(from, 0, qts, 0, i); 239 System.arraycopy(from, i + 1, qts, i, from.length - i - 1); 240 from = qts; 241 return; 242 } 243 } 244 throw new MedorException("QualifiedTable " + qt + " is not in leaf " 245 + this); 246 } 247 248 public boolean containsQualifiedTable(QualifiedTable qt) { 249 if (from == null) 250 return false; 251 for (int i = 0; i < from.length; i++) { 252 if (from[i] == qt) 253 return true; 254 } 255 return false; 256 } 257 258 264 public RdbExpField addRdbField(RdbExpField rdbField) 265 throws QueryLeafException { 266 rdbField.setQueryLeaf(this); 267 name2field.put(rdbField.getName(), rdbField); 268 fields.add(rdbField); 269 return rdbField; 270 } 271 272 public void removeRdbField(RdbExpField rdbField) throws QueryLeafException { 273 name2field.remove(rdbField.getName()); 274 fields.remove(rdbField); 275 } 276 277 public void resetSqlRequest() { 278 noGroupBy = false; 279 query = null; 280 } 281 282 public String getSqlRequest(ParameterOperand[] pos, boolean rangeStartAt, 283 boolean rangeSize) throws MedorException, ExpressionException { 284 return getSqlRequest(pos, null, rangeStartAt, rangeSize); 285 } 286 287 private static final RdbAdapter BASIC = new BasicRdbAdapter(); 288 289 private RdbAdapter sqlAdapter() { 290 if (rdbAdapter == null) { 291 return BASIC; 292 } else { 293 return rdbAdapter; 294 } 295 } 296 297 public String getSqlRequest(ParameterOperand[] pos, ArrayList selectFields, 298 boolean rangeStart, boolean rangeSize) throws MedorException, 299 ExpressionException { 300 boolean debug = logger != null && logger.isLoggable(BasicLevel.DEBUG); 301 if (debug) { 302 logger.log(BasicLevel.DEBUG, "Entering getSqlRequest for " + this); 303 } 304 if (canReuseSQL && query != null) { 305 if (debug) { 306 logger.log(BasicLevel.DEBUG, "Query already computed " + query); 307 } 308 return query; 309 } 310 if (selectFields == null) { 311 if (debug) { 312 logger.log(BasicLevel.DEBUG, 313 "Setting selectFields (was null) to local fields"); 314 } 315 selectFields = fields; 316 } 317 String where = (sqlFilter == null ? "" 318 : parseExpression(sqlFilter, pos)); 319 if (debug) { 320 logger.log(BasicLevel.DEBUG, "WHERE clause for " + this + " : " 321 + where); 322 } 323 ArrayList allSelected = new ArrayList (); 325 allSelected.addAll(selectFields); 326 OrderField[] odfs = getOrderBy(); 327 if (getDistinct() && odfs != null) { 328 for (int i = 0; i < odfs.length; i++) { 329 Object orderField = odfs[i].getField(); 330 if (!allSelected.contains(orderField)) { 331 allSelected.add(orderField); 332 } 333 } 334 } 335 String from; 336 if (rootJoinedTables != null && rootJoinedTables.size() > 0) { 337 if (debug) { 338 logger.log(BasicLevel.DEBUG, 339 "Query with rootJoinedTables (adapter is " 340 + rdbAdapterName + " - " + rdbAdapter + ")"); 341 } 342 from = sqlAdapter().getFromClause(rootJoinedTables); 343 } else { 344 if (debug) { 345 logger.log(BasicLevel.DEBUG, 346 "Query without rootJoinedTables (adapter is " 347 + rdbAdapterName + " - " + rdbAdapter + ")"); 348 } 349 from = getFromList(); 350 } 351 352 String orderBy = getOrderByClause(); 353 String groupBy = groupByFields.isEmpty() ? null : getGroupByString(); 354 355 query = sqlAdapter().getQuery(getSelectList("", allSelected, true), 356 from, where, orderBy, groupBy, rangeStart, rangeSize); 357 358 if (orderBy != null) { 361 query = sqlAdapter().handleOrderBy(query); 362 } 363 if (!canReuseSQL) { 364 canReuseSQL = true; 368 if (pos != null) { 369 for (int i = 0; i < pos.length && canReuseSQL; i++) { 370 if (((ParameterOperand) pos[i]).getType().getTypeCode() == QType.TYPECODE_COLLECTION) { 371 canReuseSQL = false; 372 } 373 } 374 } 375 } 376 return query; 377 } 378 379 private String getOrderByClause() { 380 OrderField[] orderByFields = getOrderBy(); 381 if (orderByFields == null || orderByFields.length == 0) { 382 return null; 383 } 384 StringBuffer sb = new StringBuffer (); 385 String sep = ""; 386 for (int cpt = 0; (cpt < orderByFields.length); cpt++) { 387 sb.append(sep); 388 sep = ", "; 389 sb.append(getQualifiedFieldName((RdbExpField) orderByFields[cpt] 390 .getField())); 391 sb.append(orderByFields[cpt].getDesc() ? " DESC" : " ASC"); 392 } 393 return sb.toString(); 394 } 395 396 400 private String getGroupByString() { 401 String groupBy = ""; 402 for (int i = 0; i < groupByFields.size(); i++) { 403 groupBy += getQualifiedFieldName((RdbExpField) (groupByFields.get(i))); 404 if (i < groupByFields.size() - 1) { 405 groupBy += ", "; 406 } 407 } 408 return groupBy; 409 } 410 411 422 public void setQueryFilter(Expression exp) { 423 this.sqlFilter = exp; 424 } 425 426 432 public Expression getQueryFilter() { 433 return this.sqlFilter; 434 } 435 436 441 public QualifiedTable[] getQualifiedTables() { 442 return this.from; 443 } 444 445 public void addGroupBy(RdbExpField groupBy) throws QueryLeafException { 446 if (fields.contains(groupBy)) { 447 groupByFields.add(groupBy); 448 } else 449 throw new QueryLeafException("GroupBy error: RdbExpField " 450 + groupBy.getName() 451 + " does not exist in the TupleStructure of RdbQueryLeaf " 452 + this); 453 } 454 455 public RdbExpField[] getGroupByFields() { 456 return (RdbExpField[]) groupByFields 457 .toArray(new RdbExpField[groupByFields.size()]); 458 } 459 460 public void setNoGroupBy(boolean noGB) { 461 noGroupBy = noGB; 462 } 463 464 public String getGroupBy() { 465 if (groupByFields.size() != 0) { 466 StringBuffer querySB = new StringBuffer (); 467 querySB.append(" GROUP BY "); 468 for (int i = 0; i < groupByFields.size(); i++) { 469 querySB 470 .append(getQualifiedFieldName((RdbExpField) groupByFields 471 .get(i))); 472 if (i < groupByFields.size() - 1) { 473 querySB.append(", "); 474 } 475 } 476 return querySB.toString(); 477 } else 478 return ""; 479 } 480 481 495 public String getSelectList(String selectList, ArrayList selectFields, 496 boolean qualified) { 497 logger.log(BasicLevel.DEBUG, "Computing select list"); 498 selectList += (getDistinct() ? "DISTINCT " : ""); 499 for (int i = 0; i < selectFields.size(); i++) { 500 logger.log(BasicLevel.DEBUG, "Select field " + selectFields.get(i) 501 + " of node " 502 + ((QueryTreeField) selectFields.get(i)).getQueryTree()); 503 if (selectFields.get(i) instanceof RdbExpField) { 504 logger.log(BasicLevel.DEBUG, "Found RdbExpField " 505 + selectFields.get(i)); 506 if (qualified) { 507 selectList += getQualifiedFieldName(((RdbExpField) selectFields 508 .get(i))); 509 } else { 510 selectList += ((RdbExpField) selectFields.get(i)) 511 .getColumnName(); 512 } 513 } else { 514 logger.log(BasicLevel.DEBUG, "Found CalculatedField " 515 + selectFields.get(i)); 516 AggregateOperator op = (AggregateOperator) ((CalculatedField) selectFields 517 .get(i)).getExpression(); 518 selectList += op.getOperatorString(); 519 selectList += "("; 520 if (op.getDistinct()) { 521 selectList += "DISTINCT "; 522 } 523 if ((op instanceof Count) && (((Count) op).countAll())) { 524 selectList += "*"; 525 } else { 526 RdbExpField theField = (RdbExpField) ((FieldOperand) (op 527 .getExpression(0))).getField(); 528 if (qualified) { 529 selectList += getQualifiedFieldName(theField); 530 } else { 531 selectList += theField.getColumnName(); 532 } 533 } 534 selectList += ")"; 535 } 536 if (i < selectFields.size() - 1) 537 selectList += ", "; 538 } 539 return selectList; 540 } 541 542 549 protected static String getQualifiedFieldName(RdbExpField field) { 550 String res = null; 551 if (field.getTable().getAliasName() == null) 552 res = field.getTable().getTableName(); 553 else 554 res = field.getTable().getAliasName(); 555 return res + "." + field.getColumnName(); 556 } 557 558 564 protected String getFromList() { 565 StringBuffer sb = new StringBuffer (); 566 for (int i = 0; i < from.length; i++) { 567 sb.append(from[i].getTableName()); 568 if (from[i].getAliasName() != null) { 569 if (rdbAdapter != null) { 570 rdbAdapter.writeTableAlias(from[i].getAliasName(), sb); 571 } else { 572 sb.append(" as "); 573 sb.append(from[i].getAliasName()); 574 } 575 } 576 if (i < from.length - 1) 577 sb.append(", "); 578 } 579 logger.log(BasicLevel.DEBUG, "FROM clause: " + sb.toString()); 580 return sb.toString(); 581 } 582 583 593 private String parseExpression(Expression exp, ParameterOperand[] pos) 594 throws ExpressionException { 595 logger.log(BasicLevel.DEBUG, "Parsing " + ExpressionPrinter.e2str(exp)); 596 return exp2where.convertExp2WhereClause(exp, rdbAdapter, this, pos); 597 } 598 599 } | Popular Tags |