1 24 25 package com.mckoi.database; 26 27 import java.util.List ; 28 import java.util.ArrayList ; 29 30 36 37 public class QueryPlan { 38 39 40 41 42 46 private static void cloneArray(Variable[] array) 47 throws CloneNotSupportedException { 48 if (array != null) { 49 for (int i = 0; i < array.length; ++i) { 50 array[i] = (Variable) array[i].clone(); 51 } 52 } 53 } 54 55 59 private static void cloneArray(Expression[] array) 60 throws CloneNotSupportedException { 61 if (array != null) { 62 for (int i = 0; i < array.length; ++i) { 63 array[i] = (Expression) array[i].clone(); 64 } 65 } 66 } 67 68 private static void indentBuffer(int level, StringBuffer buf) { 69 for (int i = 0; i < level; ++i) { 70 buf.append(' '); 71 } 72 } 73 74 75 76 78 81 public static abstract class SingleQueryPlanNode implements QueryPlanNode { 82 83 static final long serialVersionUID = -6753991881140638658L; 84 85 88 protected QueryPlanNode child; 89 90 93 protected SingleQueryPlanNode(QueryPlanNode child) { 94 this.child = child; 95 } 96 97 100 public QueryPlanNode child() { 101 return child; 102 } 103 104 107 public ArrayList discoverTableNames(ArrayList list) { 108 return child.discoverTableNames(list); 109 } 110 111 115 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 116 return child.discoverCorrelatedVariables(level, list); 117 } 118 119 122 public Object clone() throws CloneNotSupportedException { 123 SingleQueryPlanNode node = (SingleQueryPlanNode) super.clone(); 124 node.child = (QueryPlanNode) child.clone(); 125 return node; 126 } 127 128 public String titleString() { 129 return getClass().getName(); 130 } 131 132 public void debugString(int level, StringBuffer buf) { 133 indentBuffer(level, buf); 134 buf.append(titleString()); 135 buf.append('\n'); 136 child.debugString(level + 2, buf); 137 } 138 139 } 140 141 144 public static abstract class BranchQueryPlanNode implements QueryPlanNode { 145 146 static final long serialVersionUID = 2938130775577221138L; 147 148 151 protected QueryPlanNode left, right; 152 153 156 protected BranchQueryPlanNode(QueryPlanNode left, QueryPlanNode right) { 157 this.left = left; 158 this.right = right; 159 } 160 161 164 public QueryPlanNode left() { 165 return left; 166 } 167 168 171 public QueryPlanNode right() { 172 return right; 173 } 174 175 178 public ArrayList discoverTableNames(ArrayList list) { 179 return right.discoverTableNames( 180 left.discoverTableNames(list)); 181 } 182 183 187 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 188 return right.discoverCorrelatedVariables(level, 189 left.discoverCorrelatedVariables(level, list)); 190 } 191 192 195 public Object clone() throws CloneNotSupportedException { 196 BranchQueryPlanNode node = (BranchQueryPlanNode) super.clone(); 197 node.left = (QueryPlanNode) left.clone(); 198 node.right = (QueryPlanNode) right.clone(); 199 return node; 200 } 201 202 public String titleString() { 203 return getClass().getName(); 204 } 205 206 public void debugString(int level, StringBuffer buf) { 207 indentBuffer(level, buf); 208 buf.append(titleString()); 209 buf.append('\n'); 210 left.debugString(level + 2, buf); 211 right.debugString(level + 2, buf); 212 } 213 214 } 215 216 217 218 219 220 221 225 public static class FetchTableNode implements QueryPlanNode { 226 227 static final long serialVersionUID = 7545493568015241717L; 228 229 232 private TableName table_name; 233 234 237 private TableName alias_name; 238 239 public FetchTableNode(TableName table_name, TableName aliased_as) { 240 this.table_name = table_name; 241 this.alias_name = aliased_as; 242 } 243 244 247 public ArrayList discoverTableNames(ArrayList list) { 248 if (!list.contains(table_name)) { 249 list.add(table_name); 250 } 251 return list; 252 } 253 254 public Table evaluate(QueryContext context) { 255 DatabaseQueryContext db_context = (DatabaseQueryContext) context; 257 DataTable t = db_context.getTable(table_name); 258 if (alias_name != null) { 259 return new ReferenceTable(t, alias_name); 260 } 261 return t; 262 } 263 264 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 265 return list; 266 } 267 268 public Object clone() throws CloneNotSupportedException { 269 return super.clone(); 270 } 271 272 public String titleString() { 273 return "FETCH: " + table_name + " AS " + alias_name; 274 } 275 276 public void debugString(int level, StringBuffer buf) { 277 indentBuffer(level, buf); 278 buf.append(titleString()); 279 buf.append('\n'); 280 } 281 282 } 283 284 289 public static class SingleRowTableNode implements QueryPlanNode { 290 291 static final long serialVersionUID = -7180494964138911604L; 292 293 public SingleRowTableNode() { 294 } 295 296 public ArrayList discoverTableNames(ArrayList list) { 297 return list; 298 } 299 300 public Table evaluate(QueryContext context) { 301 DatabaseQueryContext db_context = (DatabaseQueryContext) context; 303 return db_context.getDatabase().getSingleRowTable(); 304 } 305 306 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 307 return list; 308 } 309 310 public Object clone() throws CloneNotSupportedException { 311 return super.clone(); 312 } 313 314 public String titleString() { 315 return "SINGLE ROW"; 316 } 317 318 public void debugString(int level, StringBuffer buf) { 319 indentBuffer(level, buf); 320 buf.append(titleString()); 321 buf.append('\n'); 322 } 323 324 } 325 326 334 public static class FetchViewNode implements QueryPlanNode { 335 336 static final long serialVersionUID = -6557333346211179284L; 337 338 341 private TableName table_name; 342 343 346 private TableName alias_name; 347 348 public FetchViewNode(TableName table_name, TableName aliased_as) { 349 this.table_name = table_name; 350 this.alias_name = aliased_as; 351 } 352 353 357 public QueryPlanNode createViewChildNode(QueryContext context) { 358 DatabaseQueryContext db = (DatabaseQueryContext) context; 359 return db.createViewQueryPlanNode(table_name); 360 } 361 362 365 public ArrayList discoverTableNames(ArrayList list) { 366 if (!list.contains(table_name)) { 367 list.add(table_name); 368 } 369 return list; 370 } 371 372 public Table evaluate(QueryContext context) { 373 374 QueryPlanNode node = createViewChildNode(context); 376 Table t = node.evaluate(context); 378 379 if (alias_name != null) { 380 return new ReferenceTable(t, alias_name); 381 } 382 else { 383 return t; 384 } 385 386 } 387 388 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 389 return list; 390 } 391 392 public Object clone() throws CloneNotSupportedException { 393 return super.clone(); 394 } 395 396 public String titleString() { 397 return "VIEW: " + table_name + " AS " + alias_name; 398 } 399 400 public void debugString(int level, StringBuffer buf) { 401 indentBuffer(level, buf); 402 buf.append(titleString()); 403 buf.append('\n'); 404 } 405 406 } 407 408 409 410 411 412 426 public static class RangeSelectNode extends SingleQueryPlanNode { 427 428 static final long serialVersionUID = -108747827391465748L; 429 430 435 private Expression expression; 436 437 public RangeSelectNode(QueryPlanNode child, Expression exp) { 438 super(child); 439 this.expression = exp; 440 } 441 442 450 private ArrayList createAndList(ArrayList list, Expression exp) { 451 return exp.breakByOperator(list, "and"); 452 } 453 454 457 private void updateRange(QueryContext context, SelectableRangeSet range, 458 DataTableColumnDef field, Expression e) { 459 Operator op = (Operator) e.last(); 460 Expression[] exps = e.split(); 461 TObject cell = exps[1].evaluate(null, null, context); 463 464 TType field_type = field.getTType(); 467 if (!cell.getTType().comparableTypes(field_type)) { 468 cell = new TObject(field_type, null); 469 } 470 471 range.intersect(op, cell); 473 } 474 475 479 private void calcRange(final QueryContext context, 480 final DataTableColumnDef field, 481 final SelectableRangeSet range, 482 final Expression exp) { 483 Operator op = (Operator) exp.last(); 484 if (op.isLogical()) { 485 if (op.is("and")) { 486 ArrayList and_list = createAndList(new ArrayList (), exp); 487 int sz = and_list.size(); 488 for (int i = 0; i < sz; ++i) { 489 updateRange(context, range, field, (Expression) and_list.get(i)); 490 } 491 } 492 else if (op.is("or")) { 493 Expression[] exps = exp.split(); 495 SelectableRangeSet left = new SelectableRangeSet(); 497 calcRange(context, field, left, exps[0]); 498 SelectableRangeSet right = new SelectableRangeSet(); 499 calcRange(context, field, right, exps[1]); 500 501 range.union(left); 503 range.union(right); 504 } 505 else { 506 throw new Error ("Unrecognised logical operator."); 507 } 508 } 509 else { 510 updateRange(context, range, field, exp); 512 } 513 514 } 515 516 517 public Table evaluate(QueryContext context) { 518 Table t = child.evaluate(context); 519 520 Expression exp = expression; 521 522 List all_vars = exp.allVariables(); 524 Variable v = null; 525 int sz = all_vars.size(); 526 for (int i = 0; i < sz; ++i) { 527 Variable cv = (Variable) all_vars.get(i); 528 if (v != null) { 529 if (!cv.equals(v)) { 530 throw new Error ("Assertion failed: " + 531 "Range plan does not contain common variable."); 532 } 533 } 534 v = cv; 535 } 536 537 int col = t.findFieldName(v); 539 if (col == -1) { 540 throw new Error ("Couldn't find column reference in table: " + v); 541 } 542 DataTableColumnDef field = t.getColumnDefAt(col); 543 SelectableRangeSet range = new SelectableRangeSet(); 545 calcRange(context, field, range, exp); 546 547 550 SelectableRange[] ranges = range.toSelectableRangeArray(); 552 return t.rangeSelect(v, ranges); 553 554 } 555 556 public ArrayList discoverTableNames(ArrayList list) { 557 return expression.discoverTableNames(super.discoverTableNames(list)); 558 } 559 560 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 561 return expression.discoverCorrelatedVariables(level, 563 super.discoverCorrelatedVariables(level, list)); 564 } 565 566 public Object clone() throws CloneNotSupportedException { 567 RangeSelectNode node = (RangeSelectNode) super.clone(); 568 node.expression = (Expression) expression.clone(); 569 return node; 570 } 571 572 public String titleString() { 573 return "RANGE: " + expression; 574 } 575 576 } 577 578 583 public static class SimpleSelectNode extends SingleQueryPlanNode { 584 585 static final long serialVersionUID = 5502157970886270867L; 586 587 590 private Variable left_var; 591 592 595 private Operator op; 596 597 600 private Expression right_expression; 601 602 public SimpleSelectNode(QueryPlanNode child, 603 Variable left_var, Operator op, 604 Expression right_expression) { 605 super(child); 606 this.left_var = left_var; 607 this.op = op; 608 this.right_expression = right_expression; 609 } 610 611 public Table evaluate(QueryContext context) { 612 Table table = child.evaluate(context); 614 615 return table.simpleSelect(context, 617 left_var, op, right_expression); 618 } 619 620 public ArrayList discoverTableNames(ArrayList list) { 621 return right_expression.discoverTableNames( 622 super.discoverTableNames(list)); 623 } 624 625 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 626 return right_expression.discoverCorrelatedVariables(level, 627 super.discoverCorrelatedVariables(level, list)); 628 } 629 630 public Object clone() throws CloneNotSupportedException { 631 SimpleSelectNode node = (SimpleSelectNode) super.clone(); 632 node.left_var = (Variable) left_var.clone(); 633 node.right_expression = (Expression) right_expression.clone(); 634 return node; 635 } 636 637 public String titleString() { 638 return "SIMPLE: " + left_var + op + right_expression; 639 } 640 641 } 642 643 648 public static class MultiColumnEquiSelectNode extends SingleQueryPlanNode { 649 650 static final long serialVersionUID = -1407710412096857588L; 651 652 655 private Variable[] columns; 656 657 660 private Expression[] values; 661 662 public MultiColumnEquiSelectNode(QueryPlanNode child, 663 Variable[] columns, Expression[] values) { 664 super(child); 665 this.columns = columns; 666 this.values = values; 667 } 668 669 public Table evaluate(QueryContext context) { 670 Table t = child.evaluate(context); 671 672 674 Operator EQUALS_OP = Operator.get("="); 676 for (int i = 0; i < columns.length; ++i) { 677 t = t.simpleSelect(context, columns[i], EQUALS_OP, values[i]); 678 } 679 680 return t; 681 } 682 683 public ArrayList discoverTableNames(ArrayList list) { 684 throw new Error ("PENDING"); 685 } 686 687 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 688 throw new Error ("PENDING"); 689 } 690 691 public Object clone() throws CloneNotSupportedException { 692 MultiColumnEquiSelectNode node = 693 (MultiColumnEquiSelectNode) super.clone(); 694 cloneArray(node.columns); 695 cloneArray(node.values); 696 return node; 697 } 698 699 } 700 701 713 public static class FunctionalSelectNode extends SingleQueryPlanNode { 714 715 static final long serialVersionUID = -1428022600352236457L; 716 717 720 private Expression expression; 721 722 public FunctionalSelectNode(QueryPlanNode child, Expression exp) { 723 super(child); 724 this.expression = exp; 725 } 726 727 public Table evaluate(QueryContext context) { 728 Table t = child.evaluate(context); 729 return t.exhaustiveSelect(context, expression); 732 } 733 734 public ArrayList discoverTableNames(ArrayList list) { 735 return expression.discoverTableNames(super.discoverTableNames(list)); 736 } 737 738 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 739 return expression.discoverCorrelatedVariables(level, 740 super.discoverCorrelatedVariables(level, list)); 741 } 742 743 public Object clone() throws CloneNotSupportedException { 744 FunctionalSelectNode node = (FunctionalSelectNode) super.clone(); 745 node.expression = (Expression) expression.clone(); 746 return node; 747 } 748 749 } 750 751 758 public static class ExhaustiveSelectNode extends SingleQueryPlanNode { 759 760 static final long serialVersionUID = -2005551680157574172L; 761 762 765 private Expression expression; 766 767 public ExhaustiveSelectNode(QueryPlanNode child, Expression exp) { 768 super(child); 769 this.expression = exp; 770 } 771 772 public Table evaluate(QueryContext context) { 773 Table t = child.evaluate(context); 774 return t.exhaustiveSelect(context, expression); 775 } 776 777 public ArrayList discoverTableNames(ArrayList list) { 778 return expression.discoverTableNames(super.discoverTableNames(list)); 779 } 780 781 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 782 return expression.discoverCorrelatedVariables(level, 783 super.discoverCorrelatedVariables(level, list)); 784 } 785 786 public Object clone() throws CloneNotSupportedException { 787 ExhaustiveSelectNode node = (ExhaustiveSelectNode) super.clone(); 788 node.expression = (Expression) expression.clone(); 789 return node; 790 } 791 792 public String titleString() { 793 return "EXHAUSTIVE: " + expression; 794 } 795 796 } 797 798 802 public static class ConstantSelectNode extends SingleQueryPlanNode { 803 804 static final long serialVersionUID = -4435336817396073146L; 805 806 809 private Expression expression; 810 811 public ConstantSelectNode(QueryPlanNode child, Expression exp) { 812 super(child); 813 this.expression = exp; 814 } 815 816 public Table evaluate(QueryContext context) { 817 TObject v = expression.evaluate(null, null, context); 819 if (v.isNull() || v.getObject().equals(Boolean.FALSE)) { 821 return child.evaluate(context).emptySelect(); 822 } 823 else { 824 return child.evaluate(context); 825 } 826 } 827 828 public ArrayList discoverTableNames(ArrayList list) { 829 return expression.discoverTableNames(super.discoverTableNames(list)); 830 } 831 832 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 833 return expression.discoverCorrelatedVariables(level, 834 super.discoverCorrelatedVariables(level, list)); 835 } 836 837 public Object clone() throws CloneNotSupportedException { 838 ConstantSelectNode node = (ConstantSelectNode) super.clone(); 839 node.expression = (Expression) expression.clone(); 840 return node; 841 } 842 843 public String titleString() { 844 return "CONSTANT: " + expression; 845 } 846 847 } 848 849 856 public static class SimplePatternSelectNode extends SingleQueryPlanNode { 857 858 static final long serialVersionUID = -8247282157310682761L; 859 860 863 private Expression expression; 864 865 public SimplePatternSelectNode(QueryPlanNode child, Expression exp) { 866 super(child); 867 this.expression = exp; 868 } 869 870 public Table evaluate(QueryContext context) { 871 Table t = child.evaluate(context); 873 Expression[] exps = expression.split(); 876 Variable lhs_var = exps[0].getVariable(); 877 if (lhs_var != null) { 878 Operator op = (Operator) expression.last(); 880 return t.simpleSelect(context, lhs_var, op, exps[1]); 881 } 882 else { 883 TObject v = expression.evaluate(null, context); 886 if (v.isNull() || v.getObject().equals(Boolean.FALSE)) { 888 return t.emptySelect(); 889 } 890 else { 891 return t; 892 } 893 } 894 } 895 896 public ArrayList discoverTableNames(ArrayList list) { 897 return expression.discoverTableNames(super.discoverTableNames(list)); 898 } 899 900 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 901 return expression.discoverCorrelatedVariables(level, 902 super.discoverCorrelatedVariables(level, list)); 903 } 904 905 public Object clone() throws CloneNotSupportedException { 906 SimplePatternSelectNode node = (SimplePatternSelectNode) super.clone(); 907 node.expression = (Expression) expression.clone(); 908 return node; 909 } 910 911 public String titleString() { 912 return "PATTERN: " + expression; 913 } 914 915 } 916 917 921 public static class SubsetNode extends SingleQueryPlanNode { 922 923 static final long serialVersionUID = 3784462788248510832L; 924 925 928 private Variable[] original_columns; 929 930 933 private Variable[] new_column_names; 934 935 936 public SubsetNode(QueryPlanNode child, 937 Variable[] original_columns, 938 Variable[] new_column_names) { 939 super(child); 940 this.original_columns = original_columns; 941 this.new_column_names = new_column_names; 942 943 } 944 945 public Table evaluate(QueryContext context) { 946 Table t = child.evaluate(context); 947 948 int sz = original_columns.length; 949 int[] col_map = new int[sz]; 950 951 959 for (int i = 0; i < sz; ++i) { 960 961 966 col_map[i] = t.findFieldName(original_columns[i]); 967 968 972 } 973 974 SubsetColumnTable col_table = new SubsetColumnTable(t); 975 col_table.setColumnMap(col_map, new_column_names); 976 977 return col_table; 978 } 979 980 982 986 public void setGivenName(TableName name) { 987 if (name != null) { 989 int sz = new_column_names.length; 990 for (int i = 0; i < sz; ++i) { 991 new_column_names[i].setTableName(name); 992 } 993 } 994 } 995 996 998 1002 public Variable[] getOriginalColumns() { 1003 return original_columns; 1004 } 1005 1006 1010 public Variable[] getNewColumnNames() { 1011 return new_column_names; 1012 } 1013 1014 public Object clone() throws CloneNotSupportedException { 1015 SubsetNode node = (SubsetNode) super.clone(); 1016 cloneArray(node.original_columns); 1017 cloneArray(node.new_column_names); 1018 return node; 1019 } 1020 1021 public String titleString() { 1022 StringBuffer buf = new StringBuffer (); 1023 buf.append("SUBSET: "); 1024 for (int i = 0; i < new_column_names.length; ++i) { 1025 buf.append(new_column_names[i]); 1026 buf.append("->"); 1027 buf.append(original_columns[i]); 1028 buf.append(", "); 1029 } 1030 return new String (buf); 1031 } 1032 1033 } 1034 1035 1039 public static class DistinctNode extends SingleQueryPlanNode { 1040 1041 static final long serialVersionUID = -1538264313804102373L; 1042 1043 1046 private Variable[] columns; 1047 1048 public DistinctNode(QueryPlanNode child, Variable[] columns) { 1049 super(child); 1050 this.columns = columns; 1051 } 1052 1053 public Table evaluate(QueryContext context) { 1054 Table t = child.evaluate(context); 1055 int sz = columns.length; 1056 int[] col_map = new int[sz]; 1057 for (int i = 0; i < sz; ++i) { 1058 col_map[i] = t.findFieldName(columns[i]); 1059 } 1060 return t.distinct(col_map); 1061 } 1062 1063 public Object clone() throws CloneNotSupportedException { 1064 DistinctNode node = (DistinctNode) super.clone(); 1065 cloneArray(node.columns); 1066 return node; 1067 } 1068 1069 public String titleString() { 1070 StringBuffer buf = new StringBuffer (); 1071 buf.append("DISTINCT: ("); 1072 for (int i = 0; i < columns.length; ++i) { 1073 buf.append(columns[i]); 1074 buf.append(", "); 1075 } 1076 buf.append(")"); 1077 return new String (buf); 1078 } 1079 1080 } 1081 1082 1086 public static class SortNode extends SingleQueryPlanNode { 1087 1088 static final long serialVersionUID = 3644480534542996928L; 1089 1090 1093 private Variable[] columns; 1094 1095 1098 private boolean[] correct_ascending; 1099 1100 public SortNode(QueryPlanNode child, Variable[] columns, 1101 boolean[] ascending) { 1102 super(child); 1103 this.columns = columns; 1104 this.correct_ascending = ascending; 1105 1106 1119 int sz = ascending.length; 1120 for (int n = 0; n < sz - 1; ++n) { 1121 if (!ascending[n]) { for (int p = n + 1; p < sz; ++p) { 1124 ascending[p] = !ascending[p]; 1125 } 1126 } 1127 } 1128 1129 } 1130 1131 public Table evaluate(QueryContext context) { 1132 Table t = child.evaluate(context); 1133 int sz = correct_ascending.length; 1135 for (int n = sz - 1; n >= 0; --n) { 1136 t = t.orderByColumn(columns[n], correct_ascending[n]); 1137 } 1138 return t; 1139 } 1140 1141 public Object clone() throws CloneNotSupportedException { 1142 SortNode node = (SortNode) super.clone(); 1143 cloneArray(node.columns); 1144 return node; 1145 } 1146 1147 public String titleString() { 1148 StringBuffer buf = new StringBuffer (); 1149 buf.append("SORT: ("); 1150 for (int i = 0; i < columns.length; ++i) { 1151 buf.append(columns[i]); 1152 if (correct_ascending[i]) { 1153 buf.append(" ASC"); 1154 } 1155 else { 1156 buf.append(" DESC"); 1157 } 1158 buf.append(", "); 1159 } 1160 buf.append(")"); 1161 return new String (buf); 1162 } 1163 1164 } 1165 1166 1173 public static class GroupNode extends SingleQueryPlanNode { 1174 1175 static final long serialVersionUID = 7140928678192396348L; 1176 1177 1180 private Variable[] columns; 1181 1182 1185 private Variable group_max_column; 1186 1187 1191 private Expression[] function_list; 1192 1193 1196 private String [] name_list; 1197 1198 1199 1200 1203 public GroupNode(QueryPlanNode child, Variable[] columns, 1204 Variable group_max_column, 1205 Expression[] function_list, String [] name_list) { 1206 super(child); 1207 this.columns = columns; 1208 this.group_max_column = group_max_column; 1209 this.function_list = function_list; 1210 this.name_list = name_list; 1211 } 1212 1213 1216 public GroupNode(QueryPlanNode child, Variable group_max_column, 1217 Expression[] function_list, String [] name_list) { 1218 this(child, null, group_max_column, function_list, name_list); 1219 } 1220 1221 public Table evaluate(QueryContext context) { 1222 Table child_table = child.evaluate(context); 1223 DatabaseQueryContext db_context = (DatabaseQueryContext) context; 1224 FunctionTable fun_table = 1225 new FunctionTable(child_table, function_list, name_list, db_context); 1226 if (columns == null) { 1228 fun_table.setWholeTableAsGroup(); 1229 } 1230 else { 1231 fun_table.createGroupMatrix(columns); 1232 } 1233 return fun_table.mergeWithReference(group_max_column); 1234 } 1235 1236 public ArrayList discoverTableNames(ArrayList list) { 1237 list = super.discoverTableNames(list); 1238 for (int i = 0; i < function_list.length; ++i) { 1239 list = function_list[i].discoverTableNames(list); 1240 } 1241 return list; 1242 } 1243 1244 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 1245 list = super.discoverCorrelatedVariables(level, list); 1246 for (int i = 0; i < function_list.length; ++i) { 1247 list = function_list[i].discoverCorrelatedVariables(level, list); 1248 } 1249 return list; 1250 } 1251 1252 public Object clone() throws CloneNotSupportedException { 1253 GroupNode node = (GroupNode) super.clone(); 1254 cloneArray(node.columns); 1255 cloneArray(node.function_list); 1256 if (group_max_column != null) { 1257 node.group_max_column = (Variable) group_max_column.clone(); 1258 } 1259 else { 1260 node.group_max_column = null; 1261 } 1262 return node; 1263 } 1264 1265 public String titleString() { 1266 StringBuffer buf = new StringBuffer (); 1267 buf.append("GROUP: ("); 1268 if (columns == null) { 1269 buf.append("WHOLE TABLE"); 1270 } 1271 else { 1272 for (int i = 0; i < columns.length; ++i) { 1273 buf.append(columns[i]); 1274 buf.append(", "); 1275 } 1276 } 1277 buf.append(")"); 1278 if (function_list != null) { 1279 buf.append(" FUNS: ["); 1280 for (int i = 0; i < function_list.length; ++i) { 1281 buf.append(function_list[i]); 1282 buf.append(", "); 1283 } 1284 buf.append("]"); 1285 } 1286 return new String (buf); 1287 } 1288 1289 } 1290 1291 1296 public static class CreateFunctionsNode extends SingleQueryPlanNode { 1297 1298 static final long serialVersionUID = -181012844247626327L; 1299 1300 1303 private Expression[] function_list; 1304 1305 1308 private String [] name_list; 1309 1310 1313 public CreateFunctionsNode(QueryPlanNode child, Expression[] function_list, 1314 String [] name_list) { 1315 super(child); 1316 this.function_list = function_list; 1317 this.name_list = name_list; 1318 } 1319 1320 public Table evaluate(QueryContext context) { 1321 Table child_table = child.evaluate(context); 1322 DatabaseQueryContext db_context = (DatabaseQueryContext) context; 1323 FunctionTable fun_table = 1324 new FunctionTable(child_table, function_list, name_list, db_context); 1325 Table t = fun_table.mergeWithReference(null); 1326 return t; 1327 } 1328 1329 public ArrayList discoverTableNames(ArrayList list) { 1330 list = super.discoverTableNames(list); 1331 for (int i = 0; i < function_list.length; ++i) { 1332 list = function_list[i].discoverTableNames(list); 1333 } 1334 return list; 1335 } 1336 1337 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 1338 list = super.discoverCorrelatedVariables(level, list); 1339 for (int i = 0; i < function_list.length; ++i) { 1340 list = function_list[i].discoverCorrelatedVariables(level, list); 1341 } 1342 return list; 1343 } 1344 1345 public Object clone() throws CloneNotSupportedException { 1346 CreateFunctionsNode node = (CreateFunctionsNode) super.clone(); 1347 cloneArray(node.function_list); 1348 return node; 1349 } 1350 1351 public String titleString() { 1352 StringBuffer buf = new StringBuffer (); 1353 buf.append("FUNCTIONS: ("); 1354 for (int i = 0; i < function_list.length; ++i) { 1355 buf.append(function_list[i]); 1356 buf.append(", "); 1357 } 1358 buf.append(")"); 1359 return new String (buf); 1360 } 1361 1362 } 1363 1364 1369 public static class MarkerNode extends SingleQueryPlanNode { 1370 1371 static final long serialVersionUID = -8321710589608765270L; 1372 1373 1376 private String mark_name; 1377 1378 1381 public MarkerNode(QueryPlanNode child, String mark_name) { 1382 super(child); 1383 this.mark_name = mark_name; 1384 } 1385 1386 public Table evaluate(QueryContext context) { 1387 Table child_table = child.evaluate(context); 1388 context.addMarkedTable(mark_name, child_table); 1389 return child_table; 1390 } 1391 1392 public Object clone() throws CloneNotSupportedException { 1393 return super.clone(); 1394 } 1395 1396 } 1397 1398 1402 public static class CachePointNode extends SingleQueryPlanNode { 1403 1404 static final long serialVersionUID = 7866310557831478639L; 1405 1406 1409 private long id; 1410 1411 private final static Object GLOB_LOCK = new Object (); 1412 private static int GLOB_ID = 0; 1413 1414 1417 public CachePointNode(QueryPlanNode child) { 1418 super(child); 1419 synchronized (GLOB_LOCK) { 1420 id = (System.currentTimeMillis() << 16) | (GLOB_ID & 0x0FFFF); 1421 ++GLOB_ID; 1422 } 1423 } 1424 1425 public Table evaluate(QueryContext context) { 1426 Table child_table = context.getCachedNode(id); 1428 if (child_table == null) { 1429 child_table = child.evaluate(context); 1431 context.putCachedNode(id, child_table); 1432 } 1433 return child_table; 1434 } 1435 1436 public Object clone() throws CloneNotSupportedException { 1437 return super.clone(); 1438 } 1439 1440 public String titleString() { 1441 return "CACHE: " + id; 1442 } 1443 1444 } 1445 1446 1447 1448 1449 1450 1451 1452 1453 1457 public static class NaturalJoinNode extends BranchQueryPlanNode { 1458 1459 static final long serialVersionUID = 942526205653132810L; 1460 1461 public NaturalJoinNode(QueryPlanNode left, QueryPlanNode right) { 1462 super(left, right); 1463 } 1464 1465 public Table evaluate(QueryContext context) { 1466 Table left_result = left.evaluate(context); 1468 return left_result.join(right.evaluate(context)); 1470 } 1471 1472 public String titleString() { 1473 return "NATURAL JOIN"; 1474 } 1475 1476 } 1477 1478 1488 public static class EquiJoinNode extends BranchQueryPlanNode { 1489 1490 static final long serialVersionUID = 113332589582049607L; 1491 1492 1495 private Variable[] left_columns; 1496 1497 1500 private Variable[] right_columns; 1501 1502 public EquiJoinNode(QueryPlanNode left, QueryPlanNode right, 1503 Variable[] left_cols, Variable[] right_cols) { 1504 super(left, right); 1505 this.left_columns = left_cols; 1506 this.right_columns = right_cols; 1507 } 1508 1509 public Table evaluate(QueryContext context) { 1510 Table left_result = left.evaluate(context); 1512 Table right_result = right.evaluate(context); 1514 1515 1518 Variable first_left = left_columns[0]; 1519 Variable first_right = right_columns[0]; 1520 1521 Operator EQUALS_OP = Operator.get("="); 1522 1523 Table result = left_result.simpleJoin(context, right_result, 1524 first_left, EQUALS_OP, new Expression(first_right)); 1525 1526 int sz = left_columns.length; 1527 if (sz > 1) { 1531 Expression rest_expression = new Expression(); 1533 for (int i = 1; i < sz; ++i) { 1534 Variable left_var = left_columns[i]; 1535 Variable right_var = right_columns[i]; 1536 rest_expression.addElement(left_var); 1537 rest_expression.addElement(right_var); 1538 rest_expression.addOperator(EQUALS_OP); 1539 } 1540 Operator AND_OP = Operator.get("and"); 1541 for (int i = 2; i < sz; ++i) { 1542 rest_expression.addOperator(AND_OP); 1543 } 1544 result = result.exhaustiveSelect(context, rest_expression); 1545 } 1546 1547 return result; 1548 } 1549 1550 public Object clone() throws CloneNotSupportedException { 1551 EquiJoinNode node = (EquiJoinNode) super.clone(); 1552 cloneArray(node.left_columns); 1553 cloneArray(node.right_columns); 1554 return node; 1555 } 1556 1557 } 1558 1559 1566 public static class JoinNode extends BranchQueryPlanNode { 1567 1568 static final long serialVersionUID = 4133205808616807832L; 1569 1570 1573 private Variable left_var; 1574 1575 1578 private Operator join_op; 1579 1580 1583 private Expression right_expression; 1584 1585 public JoinNode(QueryPlanNode left, QueryPlanNode right, 1586 Variable left_var, Operator join_op, 1587 Expression right_expression) { 1588 super(left, right); 1589 this.left_var = left_var; 1590 this.join_op = join_op; 1591 this.right_expression = right_expression; 1592 } 1593 1594 public Table evaluate(QueryContext context) { 1595 Table left_result = left.evaluate(context); 1597 Table right_result = right.evaluate(context); 1599 1600 Variable rhs_var = right_expression.getVariable(); 1603 Variable lhs_var = left_var; 1604 Operator op = join_op; 1605 if (rhs_var != null) { 1606 if (left_result.getRowCount() < right_result.getRowCount()) { 1610 right_expression = new Expression(lhs_var); 1612 lhs_var = rhs_var; 1613 op = op.reverse(); 1614 Table t = right_result; 1616 right_result = left_result; 1617 left_result = t; 1618 } 1619 } 1620 1621 return left_result.simpleJoin(context, right_result, 1623 lhs_var, op, right_expression); 1624 } 1625 1626 public ArrayList discoverTableNames(ArrayList list) { 1627 return right_expression.discoverTableNames( 1628 super.discoverTableNames(list)); 1629 } 1630 1631 public ArrayList discoverCorrelatedVariables(int level, ArrayList list) { 1632 return right_expression.discoverCorrelatedVariables(level, 1633 super.discoverCorrelatedVariables(level, list)); 1634 } 1635 1636 public Object clone() throws CloneNotSupportedException { 1637 JoinNode node = (JoinNode) super.clone(); 1638 node.left_var = (Variable) left_var.clone(); 1639 node.right_expression = (Expression) right_expression.clone(); 1640 return node; 1641 } 1642 1643 public String titleString() { 1644 return "JOIN: " + left_var + join_op + 1645 right_expression; 1646 } 1647 1648 } 1649 1650 1669 public static class LeftOuterJoinNode extends SingleQueryPlanNode { 1670 1671 static final long serialVersionUID = 8908801499550863492L; 1672 1673 1677 private String complete_mark_name; 1678 1679 public LeftOuterJoinNode(QueryPlanNode child, String complete_mark_name) { 1680 super(child); 1681 this.complete_mark_name = complete_mark_name; 1682 } 1683 1684 public Table evaluate(QueryContext context) { 1685 Table result = child.evaluate(context); 1687 Table complete_left = context.getMarkedTable(complete_mark_name); 1689 1690 Table outside = complete_left.outside(result); 1693 1694 OuterTable outer_table = new OuterTable(result); 1696 outer_table.mergeIn(outside); 1697 1698 return outer_table; 1700 } 1701 1702 public String titleString() { 1703 return "LEFT OUTER JOIN"; 1704 } 1705 1706 } 1707 1708 1716 public static class LogicalUnionNode extends BranchQueryPlanNode { 1717 1718 static final long serialVersionUID = -7783166856668779902L; 1719 1720 public LogicalUnionNode(QueryPlanNode left, QueryPlanNode right) { 1721 super(left, right); 1722 } 1723 1724 public Table evaluate(QueryContext context) { 1725 Table left_result = left.evaluate(context); 1727 Table right_result = right.evaluate(context); 1729 1730 return left_result.union(right_result); 1731 } 1732 1733 public String titleString() { 1734 return "LOGICAL UNION"; 1735 } 1736 1737 } 1738 1739 1745 public static class CompositeNode extends BranchQueryPlanNode { 1746 1747 static final long serialVersionUID = -560587816928425857L; 1748 1749 1753 private int composite_op; 1754 1755 1759 private boolean all_op; 1760 1761 public CompositeNode(QueryPlanNode left, QueryPlanNode right, 1762 int composite_op, boolean all_op) { 1763 super(left, right); 1764 this.composite_op = composite_op; 1765 this.all_op = all_op; 1766 } 1767 1768 public Table evaluate(QueryContext context) { 1769 Table left_result = left.evaluate(context); 1771 Table right_result = right.evaluate(context); 1773 1774 CompositeTable t = new CompositeTable(left_result, 1776 new Table[] { left_result, right_result }); 1777 t.setupIndexesForCompositeFunction(composite_op, all_op); 1778 1779 return t; 1780 } 1781 1782 } 1783 1784 1793 public static class NonCorrelatedAnyAllNode extends BranchQueryPlanNode { 1794 1795 static final long serialVersionUID = 7480579008259288291L; 1796 1797 1800 private Variable[] left_columns; 1801 1802 1805 private Operator sub_query_operator; 1806 1807 public NonCorrelatedAnyAllNode(QueryPlanNode left, QueryPlanNode right, 1808 Variable[] left_vars, Operator subquery_op) { 1809 super(left, right); 1810 this.left_columns = left_vars; 1811 this.sub_query_operator = subquery_op; 1812 } 1813 1814 public Table evaluate(QueryContext context) { 1815 Table left_result = left.evaluate(context); 1817 Table right_result = right.evaluate(context); 1819 1820 return TableFunctions.anyAllNonCorrelated(left_result, left_columns, 1823 sub_query_operator, right_result); 1824 } 1825 1826 public Object clone() throws CloneNotSupportedException { 1827 NonCorrelatedAnyAllNode node = (NonCorrelatedAnyAllNode) super.clone(); 1828 cloneArray(node.left_columns); 1829 return node; 1830 } 1831 1832 public String titleString() { 1833 StringBuffer buf = new StringBuffer (); 1834 buf.append("NON_CORRELATED: ("); 1835 for (int i = 0; i < left_columns.length; ++i) { 1836 buf.append(left_columns[i].toString()); 1837 } 1838 buf.append(") "); 1839 buf.append(sub_query_operator.toString()); 1840 return new String (buf); 1841 } 1842 1843 } 1844 1845} 1846 | Popular Tags |