1 10 package org.mmbase.util; 11 12 import java.util.Enumeration ; 13 import java.util.Iterator ; 14 import java.util.StringTokenizer ; 15 import java.util.Vector ; 16 17 import org.mmbase.bridge.Field; 18 import org.mmbase.core.CoreField; 19 import org.mmbase.storage.StorageManagerFactory; 20 import org.mmbase.storage.search.CompositeConstraint; 21 import org.mmbase.storage.search.Constraint; 22 import org.mmbase.storage.search.FieldCompareConstraint; 23 import org.mmbase.storage.search.FieldValueConstraint; 24 import org.mmbase.storage.search.implementation.BasicCompositeConstraint; 25 import org.mmbase.storage.search.implementation.BasicFieldValueConstraint; 26 import org.mmbase.storage.search.implementation.BasicSearchQuery; 27 import org.mmbase.storage.search.implementation.BasicStep; 28 import org.mmbase.storage.search.implementation.BasicStepField; 29 import org.mmbase.storage.search.legacy.ConstraintParser; 30 31 50 public class QueryConvertor { 51 52 static StorageManagerFactory factory = null; 53 54 61 public static String altaVista2SQL(String query, StorageManagerFactory smf) { 62 factory = smf; 63 return altaVista2SQL(query); 64 } 65 66 72 public static String altaVista2SQL(String query) { 73 if (query.indexOf("where")!=-1 || query.indexOf("WHERE")!=-1) { 74 return query; 75 } 76 77 StringBuffer buffer = new StringBuffer (64); 78 DBQuery parsedQuery = new DBQuery(query); 80 if(!query.equals("")) 82 parsedQuery.sqlConversion(buffer); 83 85 return buffer.toString(); 86 } 87 88 115 public static void setConstraint(BasicSearchQuery query, String where) { 116 117 Constraint constraint = null; 118 119 if (where == null || where.trim().length() == 0) { 120 122 } else if (where.substring(0, 6).equalsIgnoreCase("WHERE ")) { 123 constraint = 126 new ConstraintParser(query).toConstraint(where.substring(6)); 127 128 } else if (where.substring(0, 6).equalsIgnoreCase("WHERE(")) { 129 constraint = 133 new ConstraintParser(query).toConstraint(where.substring(5)); 134 135 } else { 136 DBQuery parsedQuery = new DBQuery(where); 138 constraint = parsedQuery.toConstraint(query); 139 } 140 query.setConstraint(constraint); 141 } 142 } 143 144 147 class ParseItem { 148 149 153 public void sqlConversion(StringBuffer result) { 154 } 155 156 159 public String toString() { 160 StringBuffer result = new StringBuffer (); 161 this.sqlConversion(result); 162 return result.toString(); 163 } 164 } 165 166 169 class DBQuery extends ParseItem { 170 173 public Vector items = new Vector (); 174 175 179 public DBQuery(String query) { 180 StringTokenizer parser = new StringTokenizer (query, "+-|",true); 181 ParseItem item; 182 183 while (parser.hasMoreTokens()) { 184 item = new DBConditionItem(parser.nextToken()); 185 items.addElement(item); 186 187 if (parser.hasMoreTokens()) { 188 item = new DBLogicalOperator(parser.nextToken()); 189 items.addElement(item); 190 } 191 } 192 } 193 194 198 public void sqlConversion(StringBuffer result) { 199 Enumeration enumeration = items.elements(); 200 201 result.append("WHERE "); 202 203 while (enumeration.hasMoreElements()) { 204 ((ParseItem)enumeration.nextElement()).sqlConversion(result); 205 } 206 } 207 208 214 Constraint toConstraint(BasicSearchQuery query) { 216 BasicCompositeConstraint compositeConstraint = null; 217 BasicFieldValueConstraint fieldValueConstraint = null; 218 219 Iterator iItems = items.iterator(); 220 DBLogicalOperator logicalOperator = null; 221 while (iItems.hasNext()) { 222 223 if (logicalOperator != null) { 225 226 if (compositeConstraint == null) { 228 if (logicalOperator.logOperator == DBLogicalOperator.OR) { 229 compositeConstraint 230 = new BasicCompositeConstraint( 231 CompositeConstraint.LOGICAL_OR); 232 } else { 233 compositeConstraint 234 = new BasicCompositeConstraint( 235 CompositeConstraint.LOGICAL_AND); 236 } 237 compositeConstraint.addChild(fieldValueConstraint); 238 239 } else if (compositeConstraint.getLogicalOperator() 243 == CompositeConstraint.LOGICAL_AND) { 244 if (logicalOperator.logOperator 245 == DBLogicalOperator.OR) { 246 BasicCompositeConstraint compositeConstraint2 247 = new BasicCompositeConstraint( 248 CompositeConstraint.LOGICAL_OR); 249 compositeConstraint2.addChild(compositeConstraint); 250 compositeConstraint = compositeConstraint2; 251 } 252 } else if (compositeConstraint.getLogicalOperator() 253 == CompositeConstraint.LOGICAL_OR) { 254 if (logicalOperator.logOperator 255 != DBLogicalOperator.OR) { 256 BasicCompositeConstraint compositeConstraint2 257 = new BasicCompositeConstraint( 258 CompositeConstraint.LOGICAL_AND); 259 compositeConstraint2.addChild(compositeConstraint); 260 compositeConstraint = compositeConstraint2; 261 } 262 } 263 } 264 265 DBConditionItem condition = (DBConditionItem) iItems.next(); 266 267 BasicStepField field = null; 269 Iterator iFields = query.getFields().iterator(); 270 while (iFields.hasNext()) { 271 BasicStepField field2 = (BasicStepField) iFields.next(); 272 String alias2 = field2.getStep().getAlias(); 273 if (alias2 == null) { 274 alias2 = field2.getStep().getTableName(); 275 } 276 if ((condition.prefix == null 277 || alias2.equals(condition.prefix)) 278 && field2.getFieldName().equals(condition.fieldName)) { 279 field = field2; 280 break; 281 } 282 } 283 284 if (field == null) { 285 BasicStep step = null; 287 if (condition.prefix == null) { 288 step = (BasicStep) query.getSteps().get(0); 289 } else { 290 Iterator iSteps = query.getSteps().iterator(); 291 while (iSteps.hasNext()) { 292 BasicStep step2 = (BasicStep) iSteps.next(); 293 if (step2.getAlias().equals(condition.prefix)) { 294 step = step2; 295 break; 296 } 297 } 298 if (step == null) { 299 throw new IllegalStateException ("Step with alias '" 301 + condition.prefix + "' not found in this query: " 302 + query); 303 } 304 } 305 306 CoreField coreField = step.getBuilder().getField(condition.fieldName); 307 if (coreField == null) { 308 throw new IllegalStateException ("Field with name '" 310 + condition.fieldName + "' not found in builder " 311 + step.getTableName()); 312 } else { 313 field = query.addField(step, coreField); 314 } 315 } 316 317 int fieldType = field.getType(); 318 if (fieldType == Field.TYPE_STRING 319 || fieldType == Field.TYPE_XML) { 320 fieldValueConstraint = new BasicFieldValueConstraint(field, condition.value.getValue()); 322 fieldValueConstraint.setCaseSensitive(false); 323 } else { 324 Object numericalValue = new Double (condition.value.getValue()); 326 fieldValueConstraint = new BasicFieldValueConstraint(field, numericalValue); 327 } 328 329 switch (condition.operator) { 330 case DBConditionItem.NOTEQUAL: 331 fieldValueConstraint.setOperator(FieldValueConstraint.NOT_EQUAL); 332 break; 333 334 case DBConditionItem.EQUAL: 335 if (fieldType == Field.TYPE_STRING 336 || fieldType == Field.TYPE_XML) { 337 fieldValueConstraint.setOperator(FieldCompareConstraint.LIKE); 338 } else { 339 fieldValueConstraint.setOperator(FieldCompareConstraint.EQUAL); 340 } 341 break; 342 343 case DBConditionItem.GREATER: 344 fieldValueConstraint.setOperator(FieldCompareConstraint.GREATER); 345 break; 346 347 case DBConditionItem.SMALLER: 348 fieldValueConstraint.setOperator(FieldCompareConstraint.LESS); 349 break; 350 351 case DBConditionItem.GREATEREQUAL: 352 fieldValueConstraint.setOperator(FieldCompareConstraint.GREATER_EQUAL); 353 break; 354 355 case DBConditionItem.SMALLEREQUAL: 356 fieldValueConstraint.setOperator(FieldCompareConstraint.LESS_EQUAL); 357 break; 358 359 default: 360 throw new IllegalStateException ( 362 "Invalid operator value: " + condition.operator); 363 364 } 365 366 if (compositeConstraint != null) { 368 fieldValueConstraint.setInverse(logicalOperator.logOperator 369 == DBLogicalOperator.NOT); 370 compositeConstraint.addChild(fieldValueConstraint); 371 } 372 373 if (iItems.hasNext()) { 374 logicalOperator = (DBLogicalOperator) iItems.next(); 375 } 376 } 377 378 if (compositeConstraint != null) { 379 return compositeConstraint; 380 } else { 381 return fieldValueConstraint; 382 } 383 } 384 } 385 386 400 class DBConditionItem extends ParseItem { 401 public static final int NOTEQUAL=0, EQUAL = 1, GREATER = 2, SMALLER = 3, GREATEREQUAL=4,SMALLEREQUAL=5; 402 405 406 String fieldName = null; 407 408 409 String prefix = null; 410 411 416 String identifier = null; 417 418 422 int operator = 0; 423 424 425 DBValue value = null; 426 427 431 public DBConditionItem(String item) { 432 int conditionPos; 433 char operatorChar; 434 435 conditionPos = item.indexOf('='); 436 if (conditionPos == -1) { 437 throw new IllegalArgumentException ( 438 "No '=' found in query item '" + item + "'"); 439 } 440 441 fieldName = item.substring(0, conditionPos); 442 int prefixPos = fieldName.indexOf("."); 443 if (prefixPos != -1) { 444 prefix = fieldName.substring(0, prefixPos); 445 fieldName = fieldName.substring(prefixPos + 1); 446 } 447 if (QueryConvertor.factory != null) { 448 identifier = (String )QueryConvertor.factory.getStorageIdentifier(fieldName); 449 } else { 450 identifier = fieldName; 451 } 452 if (prefix != null) { 453 identifier = prefix +"."+ identifier; 454 } 455 456 value = DBValue.abstractCreation(item.substring(conditionPos+2)); 457 458 operatorChar = item.charAt(conditionPos + 1); 459 switch (operatorChar) { 461 case '=': 462 case 'E': 463 operator = EQUAL; 464 break; 465 case 'N': 466 operator = NOTEQUAL; 467 break; 468 case 'G': 469 operator = GREATER; 470 break; 471 case 'g': 472 operator = GREATEREQUAL; 473 break; 474 case 'S': 475 operator = SMALLER; 476 break; 477 case 's': 478 operator = SMALLEREQUAL; 479 break; 480 default: 481 break; 482 } 483 } 484 485 489 public void sqlConversion(StringBuffer result) { 490 if (value instanceof DBWildcardStringValue || value instanceof DBStringValue) 491 result.append("lower(").append(identifier).append(")"); 492 else 494 result.append(identifier); 495 496 if (value instanceof DBWildcardStringValue) { 497 result.append(" LIKE "); 498 } 499 else { 500 switch (operator) { 501 case EQUAL: 502 result.append(" = "); 503 break; 504 case NOTEQUAL: 505 result.append(" <> "); 506 break; 507 case GREATER: 508 result.append(" > "); 509 break; 510 case GREATEREQUAL: 511 result.append(" >= "); 512 break; 513 case SMALLER: 514 result.append(" < "); 515 break; 516 case SMALLEREQUAL: 517 result.append(" <= "); 518 break; 519 default: 520 result.append(" = "); 521 } 522 } 523 value.sqlConversion(result); 524 } 525 } 526 527 530 class DBValue extends ParseItem { 531 532 private String value = null; 533 534 537 protected DBValue() {} 538 539 545 public static DBValue abstractCreation(String value) { 546 value = value.toLowerCase(); 547 if (value.startsWith("'")) { 548 if (value.indexOf('?') >= 0 || value.indexOf('*') >= 0) 549 return new DBWildcardStringValue(Strip.Chars(value,"' ",Strip.BOTH)); 550 else 551 return new DBStringValue(Strip.Chars(value,"' ",Strip.BOTH)); 552 } 553 else 554 return new DBNumberValue(value); 555 } 556 557 562 protected void setValue(String value) { 563 this.value = value; 564 } 565 566 571 public String getValue() { 572 return value; 573 } 574 } 575 576 579 class DBNumberValue extends DBValue { 580 584 public DBNumberValue(String value) { 585 if (value == null || value.length() == 0) { 587 setValue(Integer.toString(Integer.MIN_VALUE)); 588 } else { 589 setValue(value); 590 } 591 } 592 593 597 public void sqlConversion(StringBuffer result) { 598 result.append(getValue()); 599 } 600 } 601 602 606 class DBStringValue extends DBValue { 607 611 public DBStringValue(String value) { 612 setValue(value); 613 } 614 615 619 public void sqlConversion(StringBuffer result) { 620 result.append("'").append(getValue()).append("'"); 621 } 622 623 } 624 625 630 class DBWildcardStringValue extends DBValue { 631 635 public DBWildcardStringValue(String value) { 636 if (value == null) { 637 value = ""; 638 } 639 setValue(value.replace('*', '%').replace('?', '_')); 640 } 641 642 646 public void sqlConversion(StringBuffer result) { 647 result.append("'").append(getValue()).append("'"); 648 } 649 } 650 651 658 class DBLogicalOperator extends ParseItem { 659 public static final char AND = '+'; 660 public static final char NOT = '-'; 661 public static final char OR ='|'; 662 663 char logOperator; 664 665 669 public DBLogicalOperator(String operator) { 670 if (operator.equals("+")) logOperator = AND; 671 else if (operator.equals("-")) logOperator = NOT; 672 else if (operator.equals("|")) logOperator = OR; 673 } 674 675 public DBLogicalOperator(char operator) { 676 logOperator = operator; 677 } 678 679 683 public void sqlConversion(StringBuffer result) { 684 switch (logOperator) { 685 case AND: 686 result.append(" AND "); 687 break; 688 case NOT: 689 result.append(" AND NOT "); 690 break; 691 case OR: 692 result.append(" OR "); 693 break; 694 default: 695 break; 696 } 697 } 698 } 699 700 | Popular Tags |