1 24 25 package com.mckoi.database; 26 27 import java.util.HashMap ; 28 import java.util.ArrayList ; 29 30 35 36 public abstract class Operator implements java.io.Serializable { 37 38 static final long serialVersionUID = 516615288995154064L; 39 40 42 45 public static final int NONE = 0, ANY = 1, ALL = 2; 46 47 49 52 private String op; 53 54 58 private int set_type; 59 60 63 private int precedence; 64 65 68 protected Operator(String op) { 69 this(op, 0, NONE); 70 } 71 72 protected Operator(String op, int precedence) { 73 this(op, precedence, NONE); 74 } 75 76 protected Operator(String op, int precedence, int set_type) { 77 if (set_type != NONE && set_type != ANY && set_type != ALL) { 78 throw new Error ("Invalid set_type."); 79 } 80 this.op = op; 81 this.precedence = precedence; 82 this.set_type = set_type; 83 } 84 85 86 89 public boolean is(String given_op) { 90 return given_op.equals(op); 91 } 92 93 public abstract TObject eval(TObject ob1, TObject ob2, 94 GroupResolver group, VariableResolver resolver, 95 QueryContext context); 96 97 public int precedence() { 98 return precedence; 99 } 100 101 public boolean isCondition() { 102 return (equals(eq_op) || 103 equals(neq_op) || 104 equals(g_op) || 105 equals(l_op) || 106 equals(geq_op) || 107 equals(leq_op) || 108 equals(is_op) || 109 equals(isn_op)); 110 } 111 112 public boolean isMathematical() { 113 return (equals(add_op) || 114 equals(sub_op) || 115 equals(mul_op) || 116 equals(div_op) || 117 equals(concat_op)); 118 } 119 120 public boolean isPattern() { 121 return (equals(like_op) || 122 equals(nlike_op) || 123 equals(regex_op)); 124 } 125 126 127 public boolean isLogical() { 128 return (equals(and_op) || 129 equals(or_op)); 130 } 131 132 public boolean isNot() { 133 return equals(not_op); 134 } 135 136 public boolean isSubQuery() { 137 return (set_type != NONE || 138 equals(in_op) || 139 equals(nin_op)); 140 } 141 142 146 public Operator reverse() { 147 if (equals(eq_op) || equals(neq_op) || equals(is_op) || equals(isn_op)) { 148 return this; 149 } 150 else if (equals(g_op)) { 151 return l_op; 152 } 153 else if (equals(l_op)) { 154 return g_op; 155 } 156 else if (equals(geq_op)) { 157 return leq_op; 158 } 159 else if (equals(leq_op)) { 160 return geq_op; 161 } 162 throw new Error ("Can't reverse a non conditional operator."); 163 } 164 165 168 public boolean isNotInversible() { 169 return equals(regex_op) || isMathematical(); 171 } 172 173 177 public Operator inverse() { 178 if (isSubQuery()) { 179 int inv_type; 180 if (isSubQueryForm(ANY)) { 181 inv_type = ALL; 182 } 183 else if (isSubQueryForm(ALL)) { 184 inv_type = ANY; 185 } 186 else { 187 throw new RuntimeException ("Can not handle sub-query form."); 188 } 189 190 Operator inv_op = Operator.get(op).inverse(); 191 192 return inv_op.getSubQueryForm(inv_type); 193 } 194 else if (equals(eq_op)) { 195 return neq_op; 196 } 197 else if (equals(neq_op)) { 198 return eq_op; 199 } 200 else if (equals(g_op)) { 201 return leq_op; 202 } 203 else if (equals(l_op)) { 204 return geq_op; 205 } 206 else if (equals(geq_op)) { 207 return l_op; 208 } 209 else if (equals(leq_op)) { 210 return g_op; 211 } 212 else if (equals(and_op)) { 213 return or_op; 214 } 215 else if (equals(or_op)) { 216 return and_op; 217 } 218 else if (equals(like_op)) { 219 return nlike_op; 220 } 221 else if (equals(nlike_op)) { 222 return like_op; 223 } 224 else if (equals(is_op)) { 225 return isn_op; 226 } 227 else if (equals(isn_op)) { 228 return is_op; 229 } 230 else { 231 throw new Error ("Can't inverse operator '" + op + "'"); 232 } 233 234 } 235 236 240 public boolean isSubQueryForm(int type) { 241 return type == set_type; 242 } 243 244 247 int getSubQueryFormRepresentation() { 248 return set_type; 249 } 250 251 254 public Operator getSubQueryForm(int type) { 255 Operator result_op = null; 256 if (type == ANY) { 257 result_op = (Operator) any_map.get(op); 258 } 259 else if (type == ALL) { 260 result_op = (Operator) all_map.get(op); 261 } 262 else if (type == NONE) { 263 result_op = get(op); 264 } 265 266 if (result_op == null) { 267 throw new Error ("Couldn't change the form of operator '" + op + "'."); 268 } 269 return result_op; 270 } 271 272 275 public Operator getSubQueryForm(String type_str) { 276 String s = type_str.toUpperCase(); 277 if (s.equals("SINGLE") || s.equals("ANY") || s.equals("SOME")) { 278 return getSubQueryForm(ANY); 279 } 280 else if (s.equals("ALL")) { 281 return getSubQueryForm(ALL); 282 } 283 throw new Error ("Do not understand subquery type '" + type_str + "'"); 284 } 285 286 289 public TType returnTType() { 290 if (equals(concat_op)) { 291 return TType.STRING_TYPE; 292 } 293 else if (isMathematical()) { 294 return TType.NUMERIC_TYPE; 295 } 296 else { 297 return TType.BOOLEAN_TYPE; 298 } 299 } 300 301 304 String stringRepresentation() { 305 return op; 306 } 307 308 public String toString() { 309 StringBuffer buf = new StringBuffer (); 310 buf.append(op); 311 if (set_type == ANY) { 312 buf.append(" ANY"); 313 } 314 else if (set_type == ALL) { 315 buf.append(" ALL"); 316 } 317 return new String (buf); 318 } 319 320 public boolean equals(Object ob) { 321 if (this == ob) return true; 322 Operator oob = (Operator) ob; 323 return op.equals(oob.op) && set_type == oob.set_type; 324 } 325 326 327 328 331 public static Operator get(String op) { 332 if (op.equals("+")) { return add_op; } 333 else if (op.equals("-")) { return sub_op; } 334 else if (op.equals("*")) { return mul_op; } 335 else if (op.equals("/")) { return div_op; } 336 else if (op.equals("||")) { return concat_op; } 337 338 else if (op.equals("=") | op.equals("==")) { return eq_op; } 339 else if (op.equals("<>") | op.equals("!=")) { return neq_op; } 340 else if (op.equals(">")) { return g_op; } 341 else if (op.equals("<")) { return l_op; } 342 else if (op.equals(">=")) { return geq_op; } 343 else if (op.equals("<=")) { return leq_op; } 344 345 else if (op.equals("(")) { return par1_op; } 346 else if (op.equals(")")) { return par2_op; } 347 348 op = op.toLowerCase(); 350 if (op.equals("is")) { return is_op; } 351 else if (op.equals("is not")) { return isn_op; } 352 else if (op.equals("like")) { return like_op; } 353 else if (op.equals("not like")) { return nlike_op; } 354 else if (op.equals("regex")) { return regex_op; } 355 356 else if (op.equals("in")) { return in_op; } 357 else if (op.equals("not in")) { return nin_op; } 358 359 else if (op.equals("not")) { return not_op; } 360 else if (op.equals("and")) { return and_op; } 361 else if (op.equals("or")) { return or_op; } 362 363 364 throw new Error ("Unrecognised operator type: " + op); 365 } 366 367 369 374 private static boolean isTrue(TObject bool) { 375 return (!bool.isNull() && 376 bool.getTType() instanceof TBooleanType && 377 bool.getObject().equals(Boolean.TRUE)); 378 } 379 380 381 383 private final static AddOperator add_op = new AddOperator(); 384 private final static SubtractOperator sub_op = new SubtractOperator(); 385 private final static MultiplyOperator mul_op = new MultiplyOperator(); 386 private final static DivideOperator div_op = new DivideOperator(); 387 private final static ConcatOperator concat_op = new ConcatOperator(); 388 389 private final static EqualOperator eq_op = new EqualOperator(); 390 private final static NotEqualOperator neq_op = new NotEqualOperator(); 391 private final static GreaterOperator g_op = new GreaterOperator(); 392 private final static LesserOperator l_op = new LesserOperator(); 393 private final static GreaterEqualOperator geq_op = 394 new GreaterEqualOperator(); 395 private final static LesserEqualOperator leq_op = new LesserEqualOperator(); 396 397 private final static IsOperator is_op = new IsOperator(); 398 private final static IsNotOperator isn_op = new IsNotOperator(); 399 400 private final static PatternMatchTrueOperator like_op = 401 new PatternMatchTrueOperator(); 402 private final static PatternMatchFalseOperator nlike_op = 403 new PatternMatchFalseOperator(); 404 private final static RegexOperator regex_op = new RegexOperator(); 405 406 private final static Operator in_op; 407 private final static Operator nin_op; 408 409 private final static Operator not_op = new SimpleOperator("not", 3); 410 411 private final static AndOperator and_op = new AndOperator(); 412 private final static OrOperator or_op = new OrOperator(); 413 414 private final static ParenOperator par1_op = new ParenOperator("("); 415 private final static ParenOperator par2_op = new ParenOperator(")"); 416 417 private final static HashMap any_map = new HashMap (); 419 private final static HashMap all_map = new HashMap (); 421 422 static { 423 any_map.put("=", new AnyOperator("=")); 425 any_map.put("<>", new AnyOperator("<>")); 426 any_map.put(">", new AnyOperator(">")); 427 any_map.put(">=", new AnyOperator(">=")); 428 any_map.put("<", new AnyOperator("<")); 429 any_map.put("<=", new AnyOperator("<=")); 430 431 all_map.put("=", new AllOperator("=")); 432 all_map.put("<>", new AllOperator("<>")); 433 all_map.put(">", new AllOperator(">")); 434 all_map.put(">=", new AllOperator(">=")); 435 all_map.put("<", new AllOperator("<")); 436 all_map.put("<=", new AllOperator("<=")); 437 438 in_op = (Operator) any_map.get("="); 440 nin_op = (Operator) all_map.get("<>"); 441 } 442 443 444 static class AddOperator extends Operator { 445 static final long serialVersionUID = 6995379384325694391L; 446 public AddOperator() { super("+", 10); } 447 public TObject eval(TObject ob1, TObject ob2, 448 GroupResolver group, VariableResolver resolver, 449 QueryContext context) { 450 return ob1.operatorAdd(ob2); 451 } 452 }; 453 454 static class SubtractOperator extends Operator { 455 static final long serialVersionUID = 3035882496296296786L; 456 public SubtractOperator() { super("-", 15); } 457 public TObject eval(TObject ob1, TObject ob2, 458 GroupResolver group, VariableResolver resolver, 459 QueryContext context) { 460 return ob1.operatorSubtract(ob2); 461 } 462 }; 463 464 static class MultiplyOperator extends Operator { 465 static final long serialVersionUID = 8191233936463163847L; 466 public MultiplyOperator() { super("*", 20); } 467 public TObject eval(TObject ob1, TObject ob2, 468 GroupResolver group, VariableResolver resolver, 469 QueryContext context) { 470 return ob1.operatorMultiply(ob2); 471 } 472 }; 473 474 static class DivideOperator extends Operator { 475 static final long serialVersionUID = -2695205152105036247L; 476 public DivideOperator() { super("/", 20); } 477 public TObject eval(TObject ob1, TObject ob2, 478 GroupResolver group, VariableResolver resolver, 479 QueryContext context) { 480 return ob1.operatorDivide(ob2); 481 } 482 }; 483 484 static class ConcatOperator extends Operator { 485 public ConcatOperator() { super("||", 10); } 486 public TObject eval(TObject ob1, TObject ob2, 487 GroupResolver group, VariableResolver resolver, 488 QueryContext context) { 489 return ob1.operatorConcat(ob2); 490 } 491 }; 492 493 494 495 static class EqualOperator extends Operator { 496 static final long serialVersionUID = -5022271093834866261L; 497 public EqualOperator() { super("=", 4); } 498 public TObject eval(TObject ob1, TObject ob2, 499 GroupResolver group, VariableResolver resolver, 500 QueryContext context) { 501 return ob1.operatorEquals(ob2); 502 } 503 } 504 505 static class NotEqualOperator extends Operator { 506 static final long serialVersionUID = 5868174826733282297L; 507 public NotEqualOperator() { super("<>", 4); } 508 public TObject eval(TObject ob1, TObject ob2, 509 GroupResolver group, VariableResolver resolver, 510 QueryContext context) { 511 return ob1.operatorNotEquals(ob2); 512 } 513 } 514 515 static class GreaterOperator extends Operator { 516 static final long serialVersionUID = -6870425685250387549L; 517 public GreaterOperator() { super(">", 4); } 518 public TObject eval(TObject ob1, TObject ob2, 519 GroupResolver group, VariableResolver resolver, 520 QueryContext context) { 521 return ob1.operatorGreater(ob2); 522 } 523 } 524 525 static class LesserOperator extends Operator { 526 static final long serialVersionUID = 2962736161551360032L; 527 public LesserOperator() { super("<", 4); } 528 public TObject eval(TObject ob1, TObject ob2, 529 GroupResolver group, VariableResolver resolver, 530 QueryContext context) { 531 return ob1.operatorLess(ob2); 532 } 533 } 534 535 static class GreaterEqualOperator extends Operator { 536 static final long serialVersionUID = 6040843932499067476L; 537 public GreaterEqualOperator() { super(">=", 4); } 538 public TObject eval(TObject ob1, TObject ob2, 539 GroupResolver group, VariableResolver resolver, 540 QueryContext context) { 541 return ob1.operatorGreaterEquals(ob2); 542 } 543 } 544 545 static class LesserEqualOperator extends Operator { 546 static final long serialVersionUID = 4298966494510169621L; 547 public LesserEqualOperator() { super("<=", 4); } 548 public TObject eval(TObject ob1, TObject ob2, 549 GroupResolver group, VariableResolver resolver, 550 QueryContext context) { 551 return ob1.operatorLessEquals(ob2); 552 } 553 } 554 555 static class IsOperator extends Operator { 556 static final long serialVersionUID = -5537856102106541908L; 557 public IsOperator() { super("is", 4); } 558 public TObject eval(TObject ob1, TObject ob2, 559 GroupResolver group, VariableResolver resolver, 560 QueryContext context) { 561 return ob1.operatorIs(ob2); 562 } 563 } 564 565 static class IsNotOperator extends Operator { 566 static final long serialVersionUID = 1224184162192790982L; 567 public IsNotOperator() { super("is not", 4); } 568 public TObject eval(TObject ob1, TObject ob2, 569 GroupResolver group, VariableResolver resolver, 570 QueryContext context) { 571 return ob1.operatorIs(ob2).operatorNot(); 572 } 573 } 574 575 576 577 578 static class AnyOperator extends Operator { 579 static final long serialVersionUID = 6421321961221271735L; 580 public AnyOperator(String op) { 581 super(op, 8, ANY); 582 } 583 public TObject eval(TObject ob1, TObject ob2, 584 GroupResolver group, VariableResolver resolver, 585 QueryContext context) { 586 if (ob2.getTType() instanceof TQueryPlanType) { 587 QueryPlanNode plan = (QueryPlanNode) ob2.getObject(); 589 ArrayList list = plan.discoverCorrelatedVariables(1, new ArrayList ()); 591 592 if (list.size() > 0) { 593 for (int i = 0; i < list.size(); ++i) { 595 ((CorrelatedVariable) list.get(i)).setFromResolver(resolver); 596 } 597 context.clearCache(); 599 } 600 601 Table t = plan.evaluate(context); 603 604 Operator rev_plain_op = getSubQueryForm(NONE).reverse(); 606 if (t.columnMatchesValue(0, rev_plain_op, ob1)) { 607 return TObject.BOOLEAN_TRUE; 608 } 609 return TObject.BOOLEAN_FALSE; 610 611 } 612 else if (ob2.getTType() instanceof TArrayType) { 613 Operator plain_op = getSubQueryForm(NONE); 614 Expression[] exp_list = (Expression[]) ob2.getObject(); 615 TObject ret_val = TObject.BOOLEAN_FALSE; 617 for (int i = 0; i < exp_list.length; ++i) { 618 TObject exp_item = exp_list[i].evaluate(group, resolver, context); 619 if (exp_item.isNull()) { 621 ret_val = TObject.BOOLEAN_NULL; 622 } 623 else if (isTrue(plain_op.eval(ob1, exp_item, null, null, null))) { 625 return TObject.BOOLEAN_TRUE; 626 } 627 } 628 return ret_val; 632 } 633 else { 634 throw new Error ("Unknown RHS of ANY."); 635 } 636 } 637 } 638 639 static class AllOperator extends Operator { 640 static final long serialVersionUID = -4605268759294925687L; 641 public AllOperator(String op) { 642 super(op, 8, ALL); 643 } 644 public TObject eval(TObject ob1, TObject ob2, 645 GroupResolver group, VariableResolver resolver, 646 QueryContext context) { 647 if (ob2.getTType() instanceof TQueryPlanType) { 648 649 QueryPlanNode plan = (QueryPlanNode) ob2.getObject(); 651 ArrayList list = plan.discoverCorrelatedVariables(1, new ArrayList ()); 653 654 if (list.size() > 0) { 655 for (int i = 0; i < list.size(); ++i) { 657 ((CorrelatedVariable) list.get(i)).setFromResolver(resolver); 658 } 659 context.clearCache(); 661 } 662 663 Table t = plan.evaluate(context); 665 666 Operator rev_plain_op = getSubQueryForm(NONE).reverse(); 667 if (t.allColumnMatchesValue(0, rev_plain_op, ob1)) { 668 return TObject.BOOLEAN_TRUE; 669 } 670 return TObject.BOOLEAN_FALSE; 671 672 } 673 else if (ob2.getTType() instanceof TArrayType) { 674 Operator plain_op = getSubQueryForm(NONE); 675 Expression[] exp_list = (Expression[]) ob2.getObject(); 676 TObject ret_val = TObject.BOOLEAN_TRUE; 678 for (int i = 0; i < exp_list.length; ++i) { 679 TObject exp_item = exp_list[i].evaluate(group, resolver, context); 680 if (exp_item.isNull()) { 683 ret_val = TObject.BOOLEAN_NULL; 684 } 685 else if (!isTrue(plain_op.eval(ob1, exp_item, null, null, null))) { 687 return TObject.BOOLEAN_FALSE; 688 } 689 } 690 return ret_val; 693 } 694 else { 695 throw new Error ("Unknown RHS of ALL."); 696 } 697 } 698 } 699 700 static class RegexOperator extends Operator { 701 static final long serialVersionUID = 8062751421429261272L; 702 public RegexOperator() { super("regex", 8); } 703 public TObject eval(TObject ob1, TObject ob2, 704 GroupResolver group, VariableResolver resolver, 705 QueryContext context) { 706 if (ob1.isNull()) { 707 return ob1; 708 } 709 if (ob2.isNull()) { 710 return ob2; 711 } 712 String val = ob1.castTo(TType.STRING_TYPE).toStringValue(); 713 String pattern = ob2.castTo(TType.STRING_TYPE).toStringValue(); 714 return TObject.booleanVal(PatternSearch.regexMatch( 715 context.getSystem(), pattern, val)); 716 } 717 } 718 719 static class PatternMatchTrueOperator extends Operator { 720 static final long serialVersionUID = 3038856811053114238L; 721 public PatternMatchTrueOperator() { super("like", 8); } 722 public TObject eval(TObject ob1, TObject ob2, 723 GroupResolver group, VariableResolver resolver, 724 QueryContext context) { 725 if (ob1.isNull()) { 726 return ob1; 727 } 728 if (ob2.isNull()) { 729 return ob2; 730 } 731 String val = ob1.castTo(TType.STRING_TYPE).toStringValue(); 732 String pattern = ob2.castTo(TType.STRING_TYPE).toStringValue(); 733 734 TObject result = TObject.booleanVal( 735 PatternSearch.fullPatternMatch(pattern, val, '\\')); 736 return result; 737 } 738 } 739 740 static class PatternMatchFalseOperator extends Operator { 741 static final long serialVersionUID = 7271394661743778291L; 742 public PatternMatchFalseOperator() { super("not like", 8); } 743 public TObject eval(TObject ob1, TObject ob2, 744 GroupResolver group, VariableResolver resolver, 745 QueryContext context) { 746 if (ob1.isNull()) { 747 return ob1; 748 } 749 if (ob2.isNull()) { 750 return ob2; 751 } 752 String val = ob1.castTo(TType.STRING_TYPE).toStringValue(); 753 String pattern = ob2.castTo(TType.STRING_TYPE).toStringValue(); 754 return TObject.booleanVal( 755 !PatternSearch.fullPatternMatch(pattern, val, '\\')); 756 } 757 } 758 759 static class AndOperator extends Operator { 761 static final long serialVersionUID = -6044610739300316190L; 762 public AndOperator() { super("and", 2); } 763 public TObject eval(TObject ob1, TObject ob2, 764 GroupResolver group, VariableResolver resolver, 765 QueryContext context) { 766 767 Boolean b1 = ob1.toBoolean(); 768 Boolean b2 = ob2.toBoolean(); 769 770 if (b1 == null) { 772 if (b2 != null) { 773 if (b2.equals(Boolean.FALSE)) { 774 return TObject.BOOLEAN_FALSE; 775 } 776 } 777 return TObject.BOOLEAN_NULL; 778 } 779 else if (b2 == null) { 780 if (b1.equals(Boolean.FALSE)) { 781 return TObject.BOOLEAN_FALSE; 782 } 783 return TObject.BOOLEAN_NULL; 784 } 785 786 return TObject.booleanVal(b1.equals(Boolean.TRUE) && 788 b2.equals(Boolean.TRUE)); 789 } 790 } 791 792 static class OrOperator extends Operator { 793 static final long serialVersionUID = 6505549460035023998L; 794 public OrOperator() { super("or", 1); } 795 public TObject eval(TObject ob1, TObject ob2, 796 GroupResolver group, VariableResolver resolver, 797 QueryContext context) { 798 799 Boolean b1 = ob1.toBoolean(); 800 Boolean b2 = ob2.toBoolean(); 801 802 if (b1 == null) { 804 if (b2 != null) { 805 if (b2.equals(Boolean.TRUE)) { 806 return TObject.BOOLEAN_TRUE; 807 } 808 } 809 return TObject.BOOLEAN_NULL; 810 } 811 else if (b2 == null) { 812 if (b1.equals(Boolean.TRUE)) { 813 return TObject.BOOLEAN_TRUE; 814 } 815 return TObject.BOOLEAN_NULL; 816 } 817 818 return TObject.booleanVal(b1.equals(Boolean.TRUE) || 820 b2.equals(Boolean.TRUE)); 821 822 } 823 } 824 825 826 827 828 829 830 static class ParenOperator extends Operator { 831 static final long serialVersionUID = -5720902399037456435L; 832 public ParenOperator(String paren) { super(paren); } 833 public TObject eval(TObject ob1, TObject ob2, 834 GroupResolver group, VariableResolver resolver, 835 QueryContext context) { 836 throw new Error ("Parenthese should never be evaluated!"); 837 } 838 } 839 840 static class SimpleOperator extends Operator { 841 static final long serialVersionUID = 1136249637094226133L; 842 public SimpleOperator(String str) { super(str); } 843 public SimpleOperator(String str, int prec) { super(str, prec); } 844 public TObject eval(TObject ob1, TObject ob2, 845 GroupResolver group, VariableResolver resolver, 846 QueryContext context) { 847 throw new Error ("SimpleOperator should never be evaluated!"); 848 } 849 } 850 851 } 852 | Popular Tags |