1 24 25 package com.mckoi.database.interpret; 26 27 import java.util.Collections ; 28 import java.util.ArrayList ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import com.mckoi.database.*; 32 import com.mckoi.util.BigNumber; 33 34 39 40 public class Planner { 41 42 45 private static TableName GROUP_BY_FUNCTION_TABLE = new TableName( 46 "FUNCTIONTABLE"); 47 48 49 50 56 private static void prepareSearchExpression( 57 final DatabaseConnection db, final TableExpressionFromSet from_set, 58 SearchExpression expression) throws DatabaseException { 59 62 expression.prepare(new ExpressionPreparer() { 64 public boolean canPrepare(Object element) { 65 return element instanceof TableSelectExpression; 66 } 67 public Object prepare(Object element) throws DatabaseException { 68 TableSelectExpression sq_expr = (TableSelectExpression) element; 69 TableExpressionFromSet sq_from_set = generateFromSet(sq_expr, db); 70 sq_from_set.setParent(from_set); 71 QueryPlanNode sq_plan = formQueryPlan(db, sq_expr, sq_from_set, null); 72 return new TObject(TType.QUERY_PLAN_TYPE, 74 new QueryPlan.CachePointNode(sq_plan)); 75 } 76 }); 77 78 expression.prepare(from_set.expressionQualifier()); 81 82 } 83 84 89 private static Expression filterHavingClause(Expression having_expr, 90 ArrayList aggregate_list, 91 QueryContext context) { 92 if (having_expr.size() > 1) { 93 Operator op = (Operator) having_expr.last(); 94 Expression[] exps = having_expr.split(); 96 Expression new_left = 97 filterHavingClause(exps[0], aggregate_list, context); 98 Expression new_right = 99 filterHavingClause(exps[1], aggregate_list, context); 100 Expression expr = new Expression(new_left, op, new_right); 101 return expr; 102 } 103 else { 104 if (having_expr.hasAggregateFunction(context)) { 106 aggregate_list.add(having_expr); 109 Variable v = Variable.resolve("FUNCTIONTABLE.HAVINGAG_" + 111 aggregate_list.size()); 112 return new Expression(v); 113 } 114 else { 115 return having_expr; 117 } 118 } 119 120 } 121 122 126 static TableExpressionFromSet generateFromSet( 127 TableSelectExpression select_expression, DatabaseConnection db) { 128 129 FromClause from_clause = select_expression.from_clause; 131 132 from_clause.getJoinSet().prepare(db); 134 135 TableExpressionFromSet from_set = new TableExpressionFromSet(db); 137 138 Iterator tables = from_clause.allTables().iterator(); 140 while (tables.hasNext()) { 141 FromTableDef ftdef = (FromTableDef) tables.next(); 142 String unique_key = ftdef.getUniqueKey(); 143 String alias = ftdef.getAlias(); 144 145 if (ftdef.isSubQueryTable()) { 147 TableSelectExpression sub_query = ftdef.getTableSelectExpression(); 149 TableExpressionFromSet sub_query_from_set = 150 generateFromSet(sub_query, db); 151 TableName alias_table_name = null; 153 if (alias != null) { 154 alias_table_name = new TableName(alias); 155 } 156 FromTableSubQuerySource source = 157 new FromTableSubQuerySource(db, unique_key, sub_query, 158 sub_query_from_set, alias_table_name); 159 from_set.addTable(source); 161 } 162 else { 164 String name = ftdef.getName(); 165 166 TableName table_name = db.resolveTableName(name); 168 169 if (!db.tableExists(table_name)) { 170 throw new StatementException( 171 "Table '" + table_name + "' was not found."); 172 } 173 174 TableName given_name = null; 175 if (alias != null) { 176 given_name = new TableName(alias); 177 } 178 179 TableQueryDef table_query_def = 181 db.getTableQueryDef(table_name, given_name); 182 FromTableDirectSource source = new FromTableDirectSource(db, 183 table_query_def, unique_key, given_name, table_name); 184 185 from_set.addTable(source); 186 } 187 } 189 191 ArrayList columns = select_expression.columns; 193 194 for (int i = 0; i < columns.size(); ++i) { 196 SelectColumn col = (SelectColumn) columns.get(i); 197 if (col.glob_name != null) { 199 if (col.glob_name.equals("*")) { 201 from_set.exposeAllColumns(); 202 } 203 else { 204 String tname = 206 col.glob_name.substring(0, col.glob_name.indexOf(".*")); 207 TableName tn = TableName.resolve(tname); 208 from_set.exposeAllColumnsFromSource(tn); 209 } 210 } 211 else { 212 217 String alias = col.alias; 220 Variable v = col.expression.getVariable(); 221 boolean alias_match_v = 222 (v != null && alias != null && 223 from_set.stringCompare(v.getName(), alias)); 224 if (alias != null && !alias_match_v) { 225 from_set.addFunctionRef(alias, col.expression); 226 from_set.exposeVariable(new Variable(alias)); 227 } 228 else if (v != null) { 229 Variable resolved = from_set.resolveReference(v); 230 if (resolved == null) { 231 from_set.exposeVariable(v); 232 } 233 else { 234 from_set.exposeVariable(resolved); 235 } 236 } 237 else { 238 String fun_name = col.expression.text().toString(); 239 from_set.addFunctionRef(fun_name, col.expression); 240 from_set.exposeVariable(new Variable(fun_name)); 241 } 242 } 243 244 } 246 return from_set; 247 } 248 249 259 public static QueryPlanNode formQueryPlan(DatabaseConnection db, 260 TableSelectExpression expression, TableExpressionFromSet from_set, 261 ArrayList order_by) 262 throws DatabaseException { 263 264 QueryContext context = new DatabaseQueryContext(db); 265 266 268 QuerySelectColumnSet column_set = new QuerySelectColumnSet(from_set); 270 271 ArrayList columns = expression.columns; 273 274 boolean do_subset_column = (columns.size() != 0); 277 278 for (int i = 0; i < columns.size(); ++i) { 280 SelectColumn col = (SelectColumn) columns.get(i); 281 if (col.glob_name != null) { 283 if (col.glob_name.equals("*")) { 285 column_set.selectAllColumnsFromAllSources(); 286 } 287 else { 288 String tname = 290 col.glob_name.substring(0, col.glob_name.indexOf(".*")); 291 TableName tn = TableName.resolve(tname); 292 column_set.selectAllColumnsFromSource(tn); 293 } 294 } 295 else { 296 column_set.selectSingleColumn(col); 298 } 299 300 } 302 column_set.prepare(context); 304 305 307 310 if (order_by != null) { 311 ArrayList prepared_col_set = column_set.s_col_list; 312 for (int i = 0; i < order_by.size(); ++i) { 313 ByColumn col = (ByColumn) order_by.get(i); 314 Expression exp = col.exp; 315 if (exp.size() == 1) { 316 Object last_elem = exp.last(); 317 if (last_elem instanceof TObject) { 318 BigNumber bnum = ((TObject) last_elem).toBigNumber(); 319 if (bnum.getScale() == 0) { 320 int col_ref = bnum.intValue() - 1; 321 if (col_ref >= 0 && col_ref < prepared_col_set.size()) { 322 SelectColumn scol = 323 (SelectColumn) prepared_col_set.get(col_ref); 324 col.exp = new Expression(scol.expression); 325 } 326 } 327 } 328 } 329 } 330 } 331 332 334 337 QueryTableSetPlanner table_planner = new QueryTableSetPlanner(); 338 339 for (int i = 0; i < from_set.setCount(); ++i) { 340 FromTableInterface table = from_set.getTable(i); 341 if (table instanceof FromTableSubQuerySource) { 342 344 FromTableSubQuerySource sq_table = (FromTableSubQuerySource) table; 345 TableSelectExpression sq_expr = sq_table.getTableExpression(); 346 TableExpressionFromSet sq_from_set = sq_table.getFromSet(); 347 348 QueryPlanNode sq_plan = formQueryPlan(db, sq_expr, sq_from_set, null); 350 351 if (sq_plan instanceof QueryPlan.SubsetNode) { 353 QueryPlan.SubsetNode subset_node = (QueryPlan.SubsetNode) sq_plan; 354 subset_node.setGivenName(sq_table.getAliasedName()); 355 } 356 else { 357 throw new RuntimeException ("Top plan is not a SubsetNode!"); 358 } 359 360 table_planner.addTableSource(sq_plan, sq_table); 361 } 362 else if (table instanceof FromTableDirectSource) { 363 365 FromTableDirectSource ds_table = (FromTableDirectSource) table; 366 TableName given_name = ds_table.getGivenTableName(); 367 TableName root_name = ds_table.getRootTableName(); 368 String aliased_name = null; 369 if (!root_name.equals(given_name)) { 370 aliased_name = given_name.getName(); 371 } 372 373 QueryPlanNode ds_plan = ds_table.createFetchQueryPlanNode(); 374 table_planner.addTableSource(ds_plan, ds_table); 375 } 376 else { 377 throw new RuntimeException ( 378 "Unknown table source instance: " + table.getClass()); 379 } 380 381 } 382 383 385 SearchExpression where_clause = expression.where_clause; 387 SearchExpression having_clause = expression.having_clause; 388 389 JoiningSet join_set = expression.from_clause.getJoinSet(); 391 392 boolean all_inner_joins = true; 395 for (int i = 0; i < join_set.getTableCount() - 1; ++i) { 396 int type = join_set.getJoinType(i); 397 if (type != JoiningSet.INNER_JOIN) { 398 all_inner_joins = false; 399 } 400 } 401 402 for (int i = 0; i < join_set.getTableCount() - 1; ++i) { 404 int type = join_set.getJoinType(i); 405 Expression on_expression = join_set.getOnExpression(i); 406 407 if (all_inner_joins) { 408 if (on_expression != null) { 411 where_clause.appendExpression(on_expression); 412 } 413 } 414 else { 415 if (type == JoiningSet.INNER_JOIN && on_expression == null) { 417 } 419 else { 420 if (on_expression == null) { 423 throw new RuntimeException ("No ON expression in join."); 424 } 425 on_expression.prepare(from_set.expressionQualifier()); 427 table_planner.setJoinInfoBetweenSources(i, type, on_expression); 429 } 430 } 431 432 } 433 434 prepareSearchExpression(db, from_set, where_clause); 437 prepareSearchExpression(db, from_set, having_clause); 438 439 ArrayList extra_aggregate_functions = new ArrayList (); 443 Expression new_having_clause = null; 444 if (having_clause.getFromExpression() != null) { 445 new_having_clause = 446 filterHavingClause(having_clause.getFromExpression(), 447 extra_aggregate_functions, context); 448 having_clause.setFromExpression(new_having_clause); 449 } 450 451 ArrayList group_by_functions = new ArrayList (); 453 454 ArrayList group_list_in = expression.group_by; 456 int gsz = group_list_in.size(); 457 Variable[] group_by_list = new Variable[gsz]; 458 for (int i = 0; i < gsz; ++i) { 459 ByColumn by_column = (ByColumn) group_list_in.get(i); 460 Expression exp = by_column.exp; 461 exp.prepare(from_set.expressionQualifier()); 463 Variable v = exp.getVariable(); 465 466 Expression group_by_expression; 467 if (v == null) { 468 group_by_expression = exp; 469 } 470 else { 471 group_by_expression = from_set.dereferenceAssignment(v); 473 } 474 475 if (group_by_expression != null) { 476 if (group_by_expression.hasAggregateFunction(context)) { 477 throw new StatementException("Aggregate expression '" + 478 group_by_expression.text().toString() + 479 "' is not allowed in GROUP BY clause."); 480 } 481 int group_by_fun_num = group_by_functions.size(); 483 group_by_functions.add(group_by_expression); 484 v = new Variable(GROUP_BY_FUNCTION_TABLE, 485 "#GROUPBY-" + group_by_fun_num); 486 } 487 group_by_list[i] = v; 488 } 489 490 Variable groupmax_column = expression.group_max; 492 if (groupmax_column != null) { 493 Variable v = from_set.resolveReference(groupmax_column); 494 if (v == null) { 495 throw new StatementException("Could find GROUP MAX reference '" + 496 groupmax_column + "'"); 497 } 498 groupmax_column = v; 499 } 500 501 503 506 if (from_set.setCount() == 0) { 509 if (column_set.aggregate_count > 0) { 510 throw new StatementException( 511 "Invalid use of aggregate function in select with no FROM clause"); 512 } 513 ArrayList s_col_list = column_set.s_col_list; 515 int sz = s_col_list.size(); 516 String [] col_names = new String [sz]; 517 Expression[] exp_list = new Expression[sz]; 518 Variable[] subset_vars = new Variable[sz]; 519 Variable[] aliases = new Variable[sz]; 520 for (int i = 0; i < sz; ++i) { 521 SelectColumn scol = (SelectColumn) s_col_list.get(i); 522 exp_list[i] = scol.expression; 523 col_names[i] = scol.internal_name.getName(); 524 subset_vars[i] = new Variable(scol.internal_name); 525 aliases[i] = new Variable(scol.resolved_name); 526 } 527 528 return new QueryPlan.SubsetNode( 529 new QueryPlan.CreateFunctionsNode( 530 new QueryPlan.SingleRowTableNode(), exp_list, col_names), 531 subset_vars, aliases); 532 } 533 534 QueryPlanNode node = 537 table_planner.planSearchExpression(expression.where_clause); 538 539 ArrayList functions_list = column_set.function_col_list; 541 int fsz = functions_list.size(); 542 ArrayList complete_fun_list = new ArrayList (); 543 for (int i = 0; i < fsz; ++i) { 544 SelectColumn scol = (SelectColumn) functions_list.get(i); 545 complete_fun_list.add(scol.expression); 546 complete_fun_list.add(scol.internal_name.getName()); 547 } 548 for (int i = 0; i < extra_aggregate_functions.size(); ++i) { 549 complete_fun_list.add(extra_aggregate_functions.get(i)); 550 complete_fun_list.add("HAVINGAG_" + (i + 1)); 551 } 552 553 int fsz2 = complete_fun_list.size() / 2; 554 Expression[] def_fun_list = new Expression[fsz2]; 555 String [] def_fun_names = new String [fsz2]; 556 for (int i = 0; i < fsz2; ++i) { 557 def_fun_list[i] = (Expression) complete_fun_list.get(i * 2); 558 def_fun_names[i] = (String ) complete_fun_list.get((i * 2) + 1); 559 } 560 561 if (column_set.aggregate_count > 0 || gsz > 0) { 564 565 if (gsz == 0) { 568 node = new QueryPlan.GroupNode(node, groupmax_column, 569 def_fun_list, def_fun_names); 570 } 571 else { 572 int gfsz = group_by_functions.size(); 574 if (gfsz > 0) { 575 Expression[] group_fun_list = new Expression[gfsz]; 576 String [] group_fun_name = new String [gfsz]; 577 for (int i = 0; i < gfsz; ++i) { 578 group_fun_list[i] = (Expression) group_by_functions.get(i); 579 group_fun_name[i] = "#GROUPBY-" + i; 580 } 581 node = new QueryPlan.CreateFunctionsNode(node, 582 group_fun_list, group_fun_name); 583 } 584 585 node = new QueryPlan.GroupNode(node, group_by_list, groupmax_column, 587 def_fun_list, def_fun_names); 588 589 } 590 591 } 592 else { 593 if (fsz > 0) { 597 node = new QueryPlan.CreateFunctionsNode(node, 598 def_fun_list, def_fun_names); 599 } 600 } 601 602 ArrayList s_col_list = column_set.s_col_list; 604 int sz = s_col_list.size(); 605 606 if (expression.having_clause.getFromExpression() != null) { 608 Expression having_expr = having_clause.getFromExpression(); 611 substituteAliasedVariables(having_expr, s_col_list); 612 613 PlanTableSource source = table_planner.getSingleTableSource(); 614 source.updatePlan(node); 615 node = table_planner.planSearchExpression(having_clause); 616 } 617 618 QueryPlanNode right_composite = null; 620 if (expression.next_composite != null) { 621 TableSelectExpression composite_expr = expression.next_composite; 622 TableExpressionFromSet composite_from_set = 624 generateFromSet(composite_expr, db); 625 626 right_composite = 628 formQueryPlan(db, composite_expr, composite_from_set, null); 629 630 } 631 632 Variable[] aliases = null; 634 if (do_subset_column) { 635 Variable[] subset_vars = new Variable[sz]; 637 aliases = new Variable[sz]; 638 for (int i = 0; i < sz; ++i) { 639 SelectColumn scol = (SelectColumn) s_col_list.get(i); 640 subset_vars[i] = new Variable(scol.internal_name); 641 aliases[i] = new Variable(scol.resolved_name); 642 } 643 644 if (expression.distinct) { 646 node = new QueryPlan.DistinctNode(node, subset_vars); 647 } 648 649 if (right_composite == null && order_by != null) { 654 node = planForOrderBy(node, order_by, from_set, s_col_list); 655 } 656 657 node = new QueryPlan.SubsetNode(node, subset_vars, aliases); 659 660 } 661 else { 662 if (right_composite == null && order_by != null) { 664 node = planForOrderBy(node, order_by, from_set, s_col_list); 665 } 666 } 667 668 if (right_composite != null) { 670 node = new QueryPlan.CompositeNode(node, right_composite, 672 expression.composite_function, expression.is_composite_all); 673 if (order_by != null) { 675 node = planForOrderBy(node, order_by, from_set, s_col_list); 676 } 677 if (!(node instanceof QueryPlan.SubsetNode) && aliases != null) { 679 node = new QueryPlan.SubsetNode(node, aliases, aliases); 680 } 681 682 } 683 684 return node; 685 } 686 687 693 public static QueryPlanNode planForOrderBy(QueryPlanNode plan, 694 ArrayList order_by, TableExpressionFromSet from_set, 695 ArrayList s_col_list) 696 throws DatabaseException { 697 698 TableName FUNCTION_TABLE = new TableName("FUNCTIONTABLE"); 699 700 if (order_by.size() > 0) { 702 int sz = order_by.size(); 703 Variable[] order_list = new Variable[sz]; 704 boolean[] ascending_list = new boolean[sz]; 705 706 ArrayList function_orders = new ArrayList (); 707 708 for (int i = 0; i < sz; ++i) { 709 ByColumn column = (ByColumn) order_by.get(i); 710 Expression exp = column.exp; 711 ascending_list[i] = column.ascending; 712 Variable v = exp.getVariable(); 713 if (v != null) { 714 Variable new_v = from_set.resolveReference(v); 715 if (new_v == null) { 716 throw new StatementException( 717 "Can not resolve ORDER BY variable: " + v); 718 } 719 substituteAliasedVariable(new_v, s_col_list); 720 721 order_list[i] = new_v; 722 } 723 else { 724 727 exp.prepare(from_set.expressionQualifier()); 729 730 substituteAliasedVariables(exp, s_col_list); 733 734 order_list[i] = 737 new Variable(FUNCTION_TABLE, "#ORDER-" + function_orders.size()); 738 function_orders.add(exp); 739 } 740 741 743 } 744 745 int fsz = function_orders.size(); 750 if (fsz > 0) { 751 Expression[] funs = new Expression[fsz]; 752 String [] fnames = new String [fsz]; 753 for (int n = 0; n < fsz; ++n) { 754 funs[n] = (Expression) function_orders.get(n); 755 fnames[n] = "#ORDER-" + n; 756 } 757 758 if (plan instanceof QueryPlan.SubsetNode) { 759 QueryPlan.SubsetNode top_subset_node = (QueryPlan.SubsetNode) plan; 763 Variable[] mapped_names = top_subset_node.getNewColumnNames(); 764 765 plan = new QueryPlan.CreateFunctionsNode(plan, funs, fnames); 767 plan = new QueryPlan.SortNode(plan, order_list, ascending_list); 769 plan = new QueryPlan.SubsetNode(plan, mapped_names, mapped_names); 771 } 772 else { 773 plan = new QueryPlan.CreateFunctionsNode(plan, funs, fnames); 775 plan = new QueryPlan.SortNode(plan, order_list, ascending_list); 777 } 778 779 } 780 else { 781 plan = new QueryPlan.SortNode(plan, order_list, ascending_list); 784 } 785 786 } 787 788 return plan; 789 } 790 791 797 private static void substituteAliasedVariables( 798 Expression expression, ArrayList s_col_list) { 799 List all_vars = expression.allVariables(); 800 for (int i = 0; i < all_vars.size(); ++i) { 801 Variable v = (Variable) all_vars.get(i); 802 substituteAliasedVariable(v, s_col_list); 803 } 804 } 805 806 private static void substituteAliasedVariable(Variable v, 807 ArrayList s_col_list) { 808 if (s_col_list != null) { 809 int sz = s_col_list.size(); 810 for (int n = 0; n < sz; ++n) { 811 SelectColumn scol = (SelectColumn) s_col_list.get(n); 812 if (v.equals(scol.resolved_name)) { 813 v.set(scol.internal_name); 814 } 815 } 816 } 817 } 818 819 820 821 822 823 825 829 private static class QuerySelectColumnSet { 830 831 834 private static TableName FUNCTION_TABLE_NAME = 835 new TableName("FUNCTIONTABLE"); 836 837 840 private TableExpressionFromSet from_set; 841 842 845 ArrayList s_col_list; 846 847 850 ArrayList function_col_list; 851 852 856 private int running_fun_number = 0; 857 858 863 int aggregate_count = 0, constant_count = 0; 864 865 868 public QuerySelectColumnSet(TableExpressionFromSet from_set) { 869 this.from_set = from_set; 870 s_col_list = new ArrayList (); 871 function_col_list = new ArrayList (); 872 } 873 874 881 void selectSingleColumn(SelectColumn col) { 882 s_col_list.add(col); 883 } 884 885 888 void addAllFromTable(FromTableInterface table) { 889 Variable[] vars = table.allColumns(); 891 int s_col_list_max = s_col_list.size(); 892 for (int i = 0; i < vars.length; ++i) { 893 Variable v = vars[i]; 895 896 SelectColumn ncol = new SelectColumn(); 898 Expression e = new Expression(v); 899 e.text().append(v.toString()); 900 ncol.alias = null; 901 ncol.expression = e; 902 ncol.resolved_name = v; 903 ncol.internal_name = v; 904 905 selectSingleColumn(ncol); 907 } 908 } 909 910 914 void selectAllColumnsFromSource(TableName table_name) { 915 FromTableInterface table = from_set.findTable( 917 table_name.getSchema(), table_name.getName()); 918 if (table == null) { 919 throw new StatementException(table_name.toString() + 920 ".* is not a valid reference."); 921 } 922 923 addAllFromTable(table); 924 } 925 926 929 void selectAllColumnsFromAllSources() { 930 for (int p = 0; p < from_set.setCount(); ++p) { 931 FromTableInterface table = from_set.getTable(p); 932 addAllFromTable(table); 933 } 934 } 935 936 945 Variable addHiddenFunction(String fun_alias, Expression function, 946 QueryContext context) { 947 SelectColumn scol = new SelectColumn(); 948 scol.resolved_name = new Variable(fun_alias); 949 scol.alias = fun_alias; 950 scol.expression = function; 951 scol.internal_name = new Variable(FUNCTION_TABLE_NAME, fun_alias); 952 953 if (function.hasAggregateFunction(context)) { 955 ++aggregate_count; 956 } 957 else if (function.isConstant()) { 959 ++constant_count; 960 } 961 962 function_col_list.add(scol); 963 964 return scol.internal_name; 965 } 966 967 971 private void prepareSelectColumn(SelectColumn col, QueryContext context) 972 throws DatabaseException { 973 List exp_elements = col.expression.allElements(); 977 for (int n = 0; n < exp_elements.size(); ++n) { 978 if (exp_elements.get(n) instanceof TableSelectExpression) { 979 throw new StatementException( 980 "Sub-query not allowed in column list."); 981 } 982 } 983 984 col.expression.prepare(from_set.expressionQualifier()); 986 987 Variable v = col.expression.getVariable(); 990 if (v == null) { 991 993 ++running_fun_number; 994 String agg_str = Integer.toString(running_fun_number); 995 996 if (col.expression.hasAggregateFunction(context)) { 998 ++aggregate_count; 999 agg_str += "_A"; 1002 } 1003 else if (col.expression.isConstant()) { 1005 ++constant_count; 1006 } 1007 else { 1008 } 1011 function_col_list.add(col); 1012 1013 col.internal_name = new Variable(FUNCTION_TABLE_NAME, agg_str); 1014 if (col.alias == null) { 1015 col.alias = new String (col.expression.text()); 1016 } 1017 col.resolved_name = new Variable(col.alias); 1018 1019 } 1020 else { 1021 col.internal_name = v; 1023 if (col.alias == null) { 1024 col.resolved_name = v; 1025 } 1026 else { 1027 col.resolved_name = new Variable(col.alias); 1028 } 1029 } 1030 1031 } 1032 1033 1034 1037 void prepare(QueryContext context) throws DatabaseException { 1038 for (int i = 0; i < s_col_list.size(); ++i) { 1043 SelectColumn column = (SelectColumn) s_col_list.get(i); 1044 prepareSelectColumn(column, context); 1045 } 1046 } 1047 1048 1049 1050 1051 1052 } 1053 1054 1055 1056 1057 1058 1062 private static class QueryTableSetPlanner { 1063 1064 1067 private ArrayList table_list; 1068 1069 1073 private boolean has_join_occurred; 1074 1075 1076 1077 1080 public QueryTableSetPlanner() { 1081 this.table_list = new ArrayList (); 1082 has_join_occurred = false; 1083 } 1084 1085 1088 private void addPlanTableSource(PlanTableSource source) { 1089 table_list.add(source); 1090 has_join_occurred = true; 1091 } 1092 1093 1096 public boolean hasJoinOccured() { 1097 return has_join_occurred; 1098 } 1099 1100 1105 public void addTableSource(QueryPlanNode plan, 1106 FromTableInterface from_def) { 1107 Variable[] all_cols = from_def.allColumns(); 1108 String [] unique_names = new String [] { from_def.getUniqueName() }; 1109 addPlanTableSource(new PlanTableSource(plan, all_cols, unique_names)); 1110 } 1111 1112 1115 private int indexOfPlanTableSource(PlanTableSource source) { 1116 int sz = table_list.size(); 1117 for (int i = 0; i < sz; ++i) { 1118 if (table_list.get(i) == source) { 1119 return i; 1120 } 1121 } 1122 return -1; 1123 } 1124 1125 1134 public void setJoinInfoBetweenSources( 1135 int between_index, int join_type, Expression on_expr) { 1136 PlanTableSource plan_left = 1137 (PlanTableSource) table_list.get(between_index); 1138 PlanTableSource plan_right = 1139 (PlanTableSource) table_list.get(between_index + 1); 1140 plan_left.setRightJoinInfo(plan_right, join_type, on_expr); 1141 plan_right.setLeftJoinInfo(plan_left, join_type, on_expr); 1142 } 1143 1144 1148 public static PlanTableSource concatTableSources( 1149 PlanTableSource left, PlanTableSource right, QueryPlanNode plan) { 1150 1151 Variable[] new_var_list = new Variable[left.var_list.length + 1153 right.var_list.length]; 1154 int i = 0; 1155 for (int n = 0; n < left.var_list.length; ++n) { 1156 new_var_list[i] = left.var_list[n]; 1157 ++i; 1158 } 1159 for (int n = 0; n < right.var_list.length; ++n) { 1160 new_var_list[i] = right.var_list[n]; 1161 ++i; 1162 } 1163 1164 String [] new_unique_list = new String [left.unique_names.length + 1166 right.unique_names.length]; 1167 i = 0; 1168 for (int n = 0; n < left.unique_names.length; ++n) { 1169 new_unique_list[i] = left.unique_names[n]; 1170 ++i; 1171 } 1172 for (int n = 0; n < right.unique_names.length; ++n) { 1173 new_unique_list[i] = right.unique_names[n]; 1174 ++i; 1175 } 1176 1177 return new PlanTableSource(plan, new_var_list, new_unique_list); 1179 } 1180 1181 1184 public PlanTableSource mergeTables( 1185 PlanTableSource left, PlanTableSource right, 1186 QueryPlanNode merge_plan) { 1187 1188 table_list.remove(left); 1190 table_list.remove(right); 1191 PlanTableSource c_plan = concatTableSources(left, right, merge_plan); 1193 c_plan.setJoinInfoMergedBetween(left, right); 1194 c_plan.setUpdated(); 1195 addPlanTableSource(c_plan); 1196 return c_plan; 1198 } 1199 1200 1204 public PlanTableSource findTableSource(Variable ref) { 1205 int sz = table_list.size(); 1206 1207 if (sz == 1) { 1209 return (PlanTableSource) table_list.get(0); 1210 } 1211 1212 for (int i = 0; i < sz; ++i) { 1213 PlanTableSource source = (PlanTableSource) table_list.get(i); 1214 if (source.containsVariable(ref)) { 1215 return source; 1216 } 1217 } 1218 throw new RuntimeException ( 1219 "Unable to find table with variable reference: " + ref); 1220 } 1221 1222 1227 public PlanTableSource findCommonTableSource(List var_list) { 1228 if (var_list.size() == 0) { 1229 return null; 1230 } 1231 1232 PlanTableSource plan = findTableSource((Variable) var_list.get(0)); 1233 int i = 1; 1234 int sz = var_list.size(); 1235 while (i < sz) { 1236 PlanTableSource p2 = findTableSource((Variable) var_list.get(i)); 1237 if (plan != p2) { 1238 return null; 1239 } 1240 ++i; 1241 } 1242 1243 return plan; 1244 } 1245 1246 1250 public PlanTableSource findTableSourceWithUniqueKey(String key) { 1251 int sz = table_list.size(); 1252 for (int i = 0; i < sz; ++i) { 1253 PlanTableSource source = (PlanTableSource) table_list.get(i); 1254 if (source.containsUniqueKey(key)) { 1255 return source; 1256 } 1257 } 1258 throw new RuntimeException ( 1259 "Unable to find table with unique key: " + key); 1260 } 1261 1262 1265 private PlanTableSource getSingleTableSource() { 1266 if (table_list.size() != 1) { 1267 throw new RuntimeException ("Not a single table source."); 1268 } 1269 return (PlanTableSource) table_list.get(0); 1270 } 1271 1272 1278 private void setCachePoints() { 1279 int sz = table_list.size(); 1280 for (int i = 0; i < sz; ++i) { 1281 PlanTableSource plan = (PlanTableSource) table_list.get(i); 1282 if (!(plan.getPlan() instanceof QueryPlan.CachePointNode)) { 1283 plan.plan = new QueryPlan.CachePointNode(plan.getPlan()); 1284 } 1285 } 1286 } 1287 1288 1303 private PlanTableSource joinAllPlansWithVariables(List all_vars) { 1304 ArrayList touched_plans = new ArrayList (); 1306 int sz = all_vars.size(); 1307 for (int i = 0; i < sz; ++i) { 1308 Variable v = (Variable) all_vars.get(i); 1309 PlanTableSource plan = findTableSource(v); 1310 if (!touched_plans.contains(plan)) { 1311 touched_plans.add(plan); 1312 } 1313 } 1314 1317 return joinAllPlansToSingleSource(touched_plans); 1318 } 1319 1320 1328 private int canPlansBeNaturallyJoined( 1329 PlanTableSource plan1, PlanTableSource plan2) { 1330 if (plan1.left_plan == plan2 || plan1.right_plan == plan2) { 1331 return 0; 1332 } 1333 else if (plan1.left_plan != null && plan2.left_plan != null) { 1334 return 2; 1336 } 1337 else if (plan1.right_plan != null && plan2.right_plan != null) { 1338 return 1; 1340 } 1341 else if ((plan1.left_plan == null && plan2.right_plan == null) || 1342 (plan1.right_plan == null && plan2.left_plan == null)) { 1343 return 0; 1345 } 1346 else { 1347 return 2; 1349 } 1350 } 1351 1352 1369 private PlanTableSource joinAllPlansToSingleSource(List all_plans) { 1370 if (all_plans.size() == 0) { 1372 return null; 1373 } 1374 else if (all_plans.size() == 1) { 1376 return (PlanTableSource) all_plans.get(0); 1377 } 1378 1379 ArrayList working_plan_list = new ArrayList (all_plans.size()); 1381 for (int i = 0; i < all_plans.size(); ++i) { 1382 working_plan_list.add(all_plans.get(i)); 1383 } 1384 1385 while (working_plan_list.size() > 1) { 1387 PlanTableSource left_plan = (PlanTableSource) working_plan_list.get(0); 1388 PlanTableSource right_plan = 1389 (PlanTableSource) working_plan_list.get(1); 1390 int status = canPlansBeNaturallyJoined(left_plan, right_plan); 1393 if (status == 0) { 1394 PlanTableSource new_plan = naturallyJoinPlans(left_plan, right_plan); 1396 working_plan_list.remove(left_plan); 1398 working_plan_list.remove(right_plan); 1399 working_plan_list.add(0, new_plan); 1400 } 1401 else if (status == 1) { 1402 PlanTableSource new_plan = 1405 naturallyJoinPlans(left_plan, left_plan.right_plan); 1406 working_plan_list.remove(left_plan); 1407 working_plan_list.remove(left_plan.right_plan); 1408 working_plan_list.add(0, new_plan); 1409 } 1410 else if (status == 2) { 1411 PlanTableSource new_plan = 1414 naturallyJoinPlans(left_plan, left_plan.left_plan); 1415 working_plan_list.remove(left_plan); 1416 working_plan_list.remove(left_plan.left_plan); 1417 working_plan_list.add(0, new_plan); 1418 } 1419 else { 1420 throw new RuntimeException ("Unknown status: " + status); 1421 } 1422 } 1423 1424 return (PlanTableSource) working_plan_list.get(0); 1426 1427 } 1428 1429 1434 private PlanTableSource naturallyJoinPlans( 1435 PlanTableSource plan1, PlanTableSource plan2) { 1436 int join_type; 1437 Expression on_expr; 1438 PlanTableSource left_plan, right_plan; 1439 if (plan1.right_plan == plan2) { 1441 join_type = plan1.right_join_type; 1442 on_expr = plan1.right_on_expr; 1443 left_plan = plan1; 1444 right_plan = plan2; 1445 } 1446 else if (plan1.left_plan == plan2) { 1447 join_type = plan1.left_join_type; 1448 on_expr = plan1.left_on_expr; 1449 left_plan = plan2; 1450 right_plan = plan1; 1451 } 1452 else { 1453 if ((plan1.left_plan != null && plan2.left_plan != null) || 1455 (plan1.right_plan != null && plan2.right_plan != null)) { 1456 throw new RuntimeException ( 1457 "Assertion failed - plans can not be naturally join because " + 1458 "the left/right join plans clash."); 1459 } 1460 1461 QueryPlanNode node = new QueryPlan.NaturalJoinNode( 1464 plan1.getPlan(), plan2.getPlan()); 1465 return mergeTables(plan1, plan2, node); 1466 } 1467 1468 boolean outer_join; 1471 if (join_type == JoiningSet.LEFT_OUTER_JOIN) { 1472 left_plan.updatePlan(new QueryPlan.MarkerNode( 1474 left_plan.getPlan(), "OUTER_JOIN")); 1475 outer_join = true; 1476 } 1477 else if (join_type == JoiningSet.RIGHT_OUTER_JOIN) { 1478 right_plan.updatePlan(new QueryPlan.MarkerNode( 1480 right_plan.getPlan(), "OUTER_JOIN")); 1481 outer_join = true; 1482 } 1483 else if (join_type == JoiningSet.INNER_JOIN) { 1484 outer_join = false; 1486 } 1487 else { 1488 throw new RuntimeException ( 1489 "Join type (" + join_type + ") is not supported."); 1490 } 1491 1492 QueryTableSetPlanner planner = new QueryTableSetPlanner(); 1494 planner.addPlanTableSource(left_plan.copy()); 1495 planner.addPlanTableSource(right_plan.copy()); 1496 1497 1499 QueryPlanNode node = planner.logicalEvaluate(on_expr); 1501 if (outer_join) { 1503 node = new QueryPlan.LeftOuterJoinNode(node, "OUTER_JOIN"); 1504 } 1505 return mergeTables(plan1, plan2, node); 1507 1508 1511 } 1512 1513 1519 private void planAllOuterJoins() { 1520 1522 int sz = table_list.size(); 1523 if (sz <= 1) { 1524 return; 1525 } 1526 1527 ArrayList working_plan_list = new ArrayList (sz); 1529 for (int i = 0; i < sz; ++i) { 1530 working_plan_list.add(table_list.get(i)); 1531 } 1532 1533 1535 PlanTableSource plan1 = (PlanTableSource) working_plan_list.get(0); 1536 for (int i = 1; i < sz; ++i) { 1537 PlanTableSource plan2 = (PlanTableSource) working_plan_list.get(i); 1538 1539 1542 if (plan1.right_plan == plan2) { 1543 plan1 = naturallyJoinPlans(plan1, plan2); 1544 } 1545 else { 1546 plan1 = plan2; 1547 } 1548 } 1549 1550 } 1551 1552 1559 private PlanTableSource naturalJoinAll() { 1560 int sz = table_list.size(); 1561 if (sz == 1) { 1562 return (PlanTableSource) table_list.get(0); 1563 } 1564 1565 return joinAllPlansToSingleSource(table_list); 1567 } 1568 1569 1572 private static class SingleVarPlan { 1573 PlanTableSource table_source; 1574 Variable single_var; 1575 Variable variable; 1576 Expression expression; 1577 } 1578 1579 1582 private void addSingleVarPlanTo(ArrayList list, PlanTableSource table, 1583 Variable variable, Variable single_var, 1584 Expression[] exp_parts, Operator op) { 1585 Expression exp = new Expression(exp_parts[0], op, exp_parts[1]); 1586 int sz = list.size(); 1588 for (int i = 0; i < sz; ++i) { 1589 SingleVarPlan plan = (SingleVarPlan) list.get(i); 1590 if (plan.table_source == table && 1591 (variable == null || plan.variable.equals(variable))) { 1592 plan.variable = variable; 1594 plan.expression = new Expression(plan.expression, 1595 Operator.get("and"), exp); 1596 return; 1597 } 1598 } 1599 SingleVarPlan plan = new SingleVarPlan(); 1601 plan.table_source = table; 1602 plan.variable = variable; 1603 plan.single_var = single_var; 1604 plan.expression = exp; 1605 list.add(plan); 1606 return; 1607 } 1608 1609 1611 private class ConstantExpressionPlan extends ExpressionPlan { 1614 private Expression expression; 1615 public ConstantExpressionPlan(Expression e) { 1616 expression = e; 1617 } 1618 public void addToPlanTree() { 1619 for (int n = 0; n < table_list.size(); ++n) { 1622 PlanTableSource plan = (PlanTableSource) table_list.get(n); 1623 plan.updatePlan(new QueryPlan.ConstantSelectNode( 1624 plan.getPlan(), expression)); 1625 } 1626 } 1627 } 1628 1629 private class SimpleSelectExpressionPlan extends ExpressionPlan { 1630 private Variable single_var; 1631 private Operator op; 1632 private Expression expression; 1633 public SimpleSelectExpressionPlan(Variable v, Operator op, 1634 Expression e) { 1635 single_var = v; 1636 this.op = op; 1637 expression = e; 1638 } 1639 public void addToPlanTree() { 1640 PlanTableSource table_source = findTableSource(single_var); 1642 table_source.updatePlan(new QueryPlan.SimpleSelectNode( 1643 table_source.getPlan(), single_var, op, expression)); 1644 } 1645 } 1646 1647 private class SimpleSingleExpressionPlan extends ExpressionPlan { 1648 private Variable single_var; 1649 private Expression expression; 1650 public SimpleSingleExpressionPlan(Variable v, Expression e) { 1651 single_var = v; 1652 expression = e; 1653 } 1654 public void addToPlanTree() { 1655 PlanTableSource table_source = findTableSource(single_var); 1657 table_source.updatePlan(new QueryPlan.RangeSelectNode( 1658 table_source.getPlan(), expression)); 1659 } 1660 } 1661 1662 private class ComplexSingleExpressionPlan extends ExpressionPlan { 1663 private Variable single_var; 1664 private Expression expression; 1665 public ComplexSingleExpressionPlan(Variable v, Expression e) { 1666 single_var = v; 1667 expression = e; 1668 } 1669 public void addToPlanTree() { 1670 PlanTableSource table_source = findTableSource(single_var); 1672 table_source.updatePlan(new QueryPlan.ExhaustiveSelectNode( 1673 table_source.getPlan(), expression)); 1674 } 1675 } 1676 1677 private class SimplePatternExpressionPlan extends ExpressionPlan { 1678 private Variable single_var; 1679 private Expression expression; 1680 public SimplePatternExpressionPlan(Variable v, Expression e) { 1681 single_var = v; 1682 expression = e; 1683 } 1684 public void addToPlanTree() { 1685 PlanTableSource table_source = findTableSource(single_var); 1687 table_source.updatePlan(new QueryPlan.SimplePatternSelectNode( 1688 table_source.getPlan(), expression)); 1689 } 1690 } 1691 1692 private class ExhaustiveSelectExpressionPlan extends ExpressionPlan { 1693 private Expression expression; 1694 public ExhaustiveSelectExpressionPlan(Expression e) { 1695 expression = e; 1696 } 1697 public void addToPlanTree() { 1698 List all_vars = expression.allVariables(); 1700 PlanTableSource table_source = joinAllPlansWithVariables(all_vars); 1702 table_source.updatePlan(new QueryPlan.ExhaustiveSelectNode( 1704 table_source.getPlan(), expression)); 1705 } 1706 } 1707 1708 private class ExhaustiveSubQueryExpressionPlan extends ExpressionPlan { 1709 private List all_vars; 1710 private Expression expression; 1711 public ExhaustiveSubQueryExpressionPlan(List vars, Expression e) { 1712 this.all_vars = vars; 1713 this.expression = e; 1714 } 1715 public void addToPlanTree() { 1716 PlanTableSource table_source = joinAllPlansWithVariables(all_vars); 1717 table_source.updatePlan(new QueryPlan.ExhaustiveSelectNode( 1719 table_source.getPlan(), expression)); 1720 1721 } 1722 } 1723 1724 private class SimpleSubQueryExpressionPlan extends ExpressionPlan { 1725 private Expression expression; 1726 public SimpleSubQueryExpressionPlan(Expression e) { 1727 this.expression = e; 1728 } 1729 public void addToPlanTree() { 1730 Operator op = (Operator) expression.last(); 1731 Expression[] exps = expression.split(); 1732 Variable left_var = exps[0].getVariable(); 1733 QueryPlanNode right_plan = exps[1].getQueryPlanNode(); 1734 1735 PlanTableSource table_source = findTableSource(left_var); 1737 QueryPlanNode left_plan = table_source.getPlan(); 1739 table_source.updatePlan( 1741 new QueryPlan.NonCorrelatedAnyAllNode( 1742 left_plan, right_plan, new Variable[] { left_var }, op)); 1743 } 1744 } 1745 1746 private class ExhaustiveJoinExpressionPlan extends ExpressionPlan { 1747 private Expression expression; 1748 public ExhaustiveJoinExpressionPlan(Expression e) { 1749 this.expression = e; 1750 } 1751 public void addToPlanTree() { 1752 List all_vars = expression.allVariables(); 1754 PlanTableSource all_plan = joinAllPlansWithVariables(all_vars); 1756 all_plan.updatePlan(new QueryPlan.ExhaustiveSelectNode( 1758 all_plan.getPlan(), expression)); 1759 } 1760 } 1761 1762 private class StandardJoinExpressionPlan extends ExpressionPlan { 1763 private Expression expression; 1764 public StandardJoinExpressionPlan(Expression e) { 1765 this.expression = e; 1766 } 1767 public void addToPlanTree() { 1768 1769 Expression[] exps = expression.split(); 1771 1772 Variable lhs_v = exps[0].getVariable(); 1774 Variable rhs_v = exps[1].getVariable(); 1775 List lhs_vars = exps[0].allVariables(); 1776 List rhs_vars = exps[1].allVariables(); 1777 1778 Operator op = (Operator) expression.last(); 1780 1781 PlanTableSource lhs_plan = joinAllPlansWithVariables(lhs_vars); 1784 PlanTableSource rhs_plan = joinAllPlansWithVariables(rhs_vars); 1785 1786 if (lhs_plan != rhs_plan) { 1789 1790 1793 if (lhs_v != null || rhs_v != null) { 1794 QueryPlan.JoinNode join_node; 1797 if (lhs_v == null && rhs_v != null) { 1798 join_node = new QueryPlan.JoinNode( 1800 rhs_plan.getPlan(), lhs_plan.getPlan(), 1801 rhs_v, op.reverse(), exps[0]); 1802 mergeTables(rhs_plan, lhs_plan, join_node); 1803 } 1804 else { 1805 join_node = new QueryPlan.JoinNode( 1807 lhs_plan.getPlan(), rhs_plan.getPlan(), 1808 lhs_v, op, exps[1]); 1809 mergeTables(lhs_plan, rhs_plan, join_node); 1810 } 1811 return; 1813 } 1814 1815 } 1817 1823 List all_vars = expression.allVariables(); 1825 PlanTableSource all_plan = joinAllPlansWithVariables(all_vars); 1827 all_plan.updatePlan(new QueryPlan.ExhaustiveSelectNode( 1829 all_plan.getPlan(), expression)); 1830 } 1831 } 1832 1833 private class SubLogicExpressionPlan extends ExpressionPlan { 1834 private Expression expression; 1835 public SubLogicExpressionPlan(Expression e) { 1836 this.expression = e; 1837 } 1838 public void addToPlanTree() { 1839 planForExpression(expression); 1840 } 1841 } 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1856 void evaluateConstants(ArrayList constant_vars, ArrayList evaluate_order) { 1857 for (int i = 0; i < constant_vars.size(); ++i) { 1859 Expression expr = (Expression) constant_vars.get(i); 1860 ExpressionPlan exp_plan = new ConstantExpressionPlan(expr); 1862 exp_plan.setOptimizableValue(0f); 1863 evaluate_order.add(exp_plan); 1864 } 1865 } 1866 1867 1875 void evaluateSingles(ArrayList single_vars, ArrayList evaluate_order) { 1876 1877 ArrayList simple_plan_list = new ArrayList (); 1879 ArrayList complex_plan_list = new ArrayList (); 1881 1882 for (int i = 0; i < single_vars.size(); ++i) { 1884 Expression andexp = (Expression) single_vars.get(i); 1885 Operator op = (Operator) andexp.last(); 1887 1888 Expression[] exps = andexp.split(); 1890 Variable single_var; 1892 1893 if (op.isSubQuery()) { 1896 single_var = exps[0].getVariable(); 1897 if (single_var != null) { 1898 ExpressionPlan exp_plan = new SimpleSelectExpressionPlan( 1899 single_var, op, exps[1]); 1900 exp_plan.setOptimizableValue(0.2f); 1901 evaluate_order.add(exp_plan); 1902 } 1903 else { 1904 single_var = (Variable) exps[0].allVariables().get(0); 1905 ExpressionPlan exp_plan = new ComplexSingleExpressionPlan( 1906 single_var, andexp); 1907 exp_plan.setOptimizableValue(0.8f); 1908 evaluate_order.add(exp_plan); 1909 } 1910 } 1911 else { 1912 List all_vars = exps[0].allVariables(); 1914 if (all_vars.size() == 0) { 1915 Expression temp_exp = exps[0]; 1917 exps[0] = exps[1]; 1918 exps[1] = temp_exp; 1919 op = op.reverse(); 1920 single_var = (Variable) exps[0].allVariables().get(0); 1921 } 1922 else { 1923 single_var = (Variable) all_vars.get(0); 1924 } 1925 PlanTableSource table_source = findTableSource(single_var); 1927 Variable v = exps[0].getVariable(); 1929 if (v != null) { 1930 addSingleVarPlanTo(simple_plan_list, table_source, v, 1931 single_var, exps, op); 1932 } 1933 else { 1934 addSingleVarPlanTo(complex_plan_list, table_source, null, 1936 single_var, exps, op); 1937 } 1938 } 1939 } 1940 1941 int sz = simple_plan_list.size(); 1943 for (int i = 0; i < sz; ++i) { 1944 SingleVarPlan var_plan = (SingleVarPlan) simple_plan_list.get(i); 1945 ExpressionPlan exp_plan = new SimpleSingleExpressionPlan( 1946 var_plan.single_var, var_plan.expression); 1947 exp_plan.setOptimizableValue(0.2f); 1948 evaluate_order.add(exp_plan); 1949 } 1950 1951 sz = complex_plan_list.size(); 1952 for (int i = 0; i < sz; ++i) { 1953 SingleVarPlan var_plan = (SingleVarPlan) complex_plan_list.get(i); 1954 ExpressionPlan exp_plan = new ComplexSingleExpressionPlan( 1955 var_plan.single_var, var_plan.expression); 1956 exp_plan.setOptimizableValue(0.8f); 1957 evaluate_order.add(exp_plan); 1958 } 1959 1960 } 1961 1962 1968 void evaluatePatterns(ArrayList pattern_exprs, ArrayList evaluate_order) { 1969 1970 1973 for (int i = 0; i < pattern_exprs.size(); ++i) { 1974 Expression expr = (Expression) pattern_exprs.get(i); 1975 1976 Expression[] exps = expr.split(); 1977 Variable lhs_v = exps[0].getVariable(); 1980 if (expr.isConstant()) { 1981 ExpressionPlan expr_plan = new ConstantExpressionPlan(expr); 1982 expr_plan.setOptimizableValue(0f); 1983 evaluate_order.add(expr_plan); 1984 } 1985 else if (lhs_v != null && exps[1].isConstant()) { 1986 ExpressionPlan expr_plan = 1987 new SimplePatternExpressionPlan(lhs_v, expr); 1988 expr_plan.setOptimizableValue(0.25f); 1989 evaluate_order.add(expr_plan); 1990 } 1991 else { 1992 ExpressionPlan expr_plan = new ExhaustiveSelectExpressionPlan(expr); 1998 expr_plan.setOptimizableValue(0.82f); 1999 evaluate_order.add(expr_plan); 2000 } 2001 2002 } 2003 2004 } 2005 2006 2012 void evaluateSubQueries(ArrayList expressions, ArrayList evaluate_order) { 2013 2014 for (int i = 0; i < expressions.size(); ++i) { 2016 Expression andexp = (Expression) expressions.get(i); 2017 2018 boolean is_exhaustive; 2019 Variable left_var = null; 2020 QueryPlanNode right_plan = null; 2021 2022 Operator op = (Operator) andexp.last(); 2024 if (op.isSubQuery()) { 2025 Expression[] exps = andexp.split(); 2027 left_var = exps[0].getVariable(); 2029 if (left_var != null) { 2030 right_plan = exps[1].getQueryPlanNode(); 2032 if (right_plan != null) { 2033 ArrayList cv = 2035 right_plan.discoverCorrelatedVariables(1, new ArrayList ()); 2036 if (cv.size() == 0) { 2039 is_exhaustive = false; 2042 } 2043 else { 2044 is_exhaustive = true; 2045 } 2046 } 2047 else { 2048 is_exhaustive = true; 2049 } 2050 } 2051 else { 2052 is_exhaustive = true; 2053 } 2054 } 2055 else { 2056 is_exhaustive = true; 2058 } 2059 2060 if (is_exhaustive) { 2062 List all_vars = andexp.allVariables(); 2065 2066 List all_correlated = 2068 andexp.discoverCorrelatedVariables(0, new ArrayList ()); 2069 int sz = all_correlated.size(); 2070 2071 if (all_vars.size() == 0 && sz == 0) { 2074 ExpressionPlan expr_plan = new ConstantExpressionPlan(andexp); 2075 expr_plan.setOptimizableValue(0f); 2076 evaluate_order.add(expr_plan); 2077 } 2078 else { 2079 2080 for (int n = 0; n < sz; ++n) { 2081 CorrelatedVariable cv = 2082 (CorrelatedVariable) all_correlated.get(n); 2083 all_vars.add(cv.getVariable()); 2084 } 2085 2086 ExpressionPlan exp_plan = new ExhaustiveSubQueryExpressionPlan( 2090 all_vars, andexp); 2091 exp_plan.setOptimizableValue(0.85f); 2092 evaluate_order.add(exp_plan); 2093 } 2094 2095 } 2096 else { 2097 2098 ExpressionPlan exp_plan = new SimpleSubQueryExpressionPlan(andexp); 2101 exp_plan.setOptimizableValue(0.3f); 2102 evaluate_order.add(exp_plan); 2103 2104 } 2105 2106 } 2108 } 2109 2110 2117 void evaluateMultiples(ArrayList multi_vars, ArrayList evaluate_order) { 2118 2119 2125 for (int i = 0; i < multi_vars.size(); ++i) { 2127 2128 Expression expr = (Expression) multi_vars.get(i); 2130 Expression[] exps = expr.split(); 2131 2132 Variable lhs_v = exps[0].getVariable(); 2134 Variable rhs_v = exps[1].getVariable(); 2135 2136 2144 if (lhs_v == null && rhs_v == null) { 2145 ExpressionPlan exp_plan = new ExhaustiveJoinExpressionPlan(expr); 2147 exp_plan.setOptimizableValue(0.68f); 2148 evaluate_order.add(exp_plan); 2149 } 2150 else if (lhs_v != null && rhs_v != null) { 2151 ExpressionPlan exp_plan = new StandardJoinExpressionPlan(expr); 2154 exp_plan.setOptimizableValue(0.60f); 2155 evaluate_order.add(exp_plan); 2156 } 2157 else { 2158 ExpressionPlan exp_plan = new StandardJoinExpressionPlan(expr); 2160 exp_plan.setOptimizableValue(0.64f); 2161 evaluate_order.add(exp_plan); 2162 } 2163 2164 } 2166 } 2167 2168 2172 void evaluateSubLogic(ArrayList sublogic_exprs, ArrayList evaluate_order) { 2173 2174each_logic_expr: 2175 for (int i = 0; i < sublogic_exprs.size(); ++i) { 2176 Expression expr = (Expression) sublogic_exprs.get(i); 2177 2178 ArrayList or_exprs = expr.breakByOperator(new ArrayList (), "or"); 2180 2181 2183 2187 2191 PlanTableSource common = null; 2192 2193 for (int n = 0; n < or_exprs.size(); ++n) { 2194 Expression or_expr = (Expression) or_exprs.get(n); 2195 List vars = or_expr.allVariables(); 2196 if (vars.size() > 0) { 2198 PlanTableSource ts = findCommonTableSource(vars); 2200 boolean or_after_joins = false; 2201 if (ts == null) { 2202 or_after_joins = true; 2204 } 2205 else if (common == null) { 2206 common = ts; 2207 } 2208 else if (common != ts) { 2209 or_after_joins = true; 2212 } 2213 2214 if (or_after_joins) { 2215 ExpressionPlan exp_plan = new SubLogicExpressionPlan(expr); 2216 exp_plan.setOptimizableValue(0.70f); 2217 evaluate_order.add(exp_plan); 2218 continue each_logic_expr; 2220 } 2221 } 2222 } 2223 2224 ExpressionPlan exp_plan = new SubLogicExpressionPlan(expr); 2227 exp_plan.setOptimizableValue(0.58f); 2228 evaluate_order.add(exp_plan); 2229 2230 } 2231 2232 } 2233 2234 2235 2237 2241 void planForExpressionList(List and_list) { 2242 2243 ArrayList sub_logic_expressions = new ArrayList (); 2244 ArrayList sub_query_expressions = new ArrayList (); 2246 ArrayList constants = new ArrayList (); 2248 ArrayList pattern_expressions = new ArrayList (); 2250 ArrayList single_vars = new ArrayList (); 2253 ArrayList multi_vars = new ArrayList (); 2255 2256 for (int i = 0; i < and_list.size(); ++i) { 2258 Object el = and_list.get(i); 2259 Expression andexp = (Expression) el; 2260 Object lob = andexp.last(); 2263 Operator op; 2264 if (!(lob instanceof Operator) || 2267 ((Operator) lob).isMathematical()) { 2268 Operator EQUAL_OP = Operator.get("="); 2269 andexp.addElement(TObject.booleanVal(true)); 2270 andexp.addOperator(EQUAL_OP); 2271 op = EQUAL_OP; 2272 } 2273 else { 2274 op = (Operator) lob; 2275 } 2276 if (op.isLogical()) { 2279 sub_logic_expressions.add(andexp); 2280 } 2281 else if (andexp.hasSubQuery()) { 2284 sub_query_expressions.add(andexp); 2285 } 2286 else if (op.isPattern()) { 2287 pattern_expressions.add(andexp); 2288 } 2289 else { List vars = andexp.allVariables(); 2292 if (vars.size() == 0) { 2293 constants.add(andexp); 2295 } 2296 else if (vars.size() == 1) { 2297 single_vars.add(andexp); 2299 } 2300 else if (vars.size() > 1) { 2301 multi_vars.add(andexp); 2304 } 2305 else { 2306 throw new Error ("Hmm, vars list size is negative!"); 2307 } 2308 } 2309 } 2310 2311 ArrayList evaluate_order = new ArrayList (); 2314 2315 evaluateConstants(constants, evaluate_order); 2318 2319 evaluateSingles(single_vars, evaluate_order); 2323 2324 evaluatePatterns(pattern_expressions, evaluate_order); 2328 2329 evaluateSubQueries(sub_query_expressions, evaluate_order); 2332 2333 evaluateMultiples(multi_vars, evaluate_order); 2336 2337 evaluateSubLogic(sub_logic_expressions, evaluate_order); 2340 2341 2342 2343 Collections.sort(evaluate_order); 2345 for (int i = 0; i < evaluate_order.size(); ++i) { 2347 ExpressionPlan plan = (ExpressionPlan) evaluate_order.get(i); 2348 plan.addToPlanTree(); 2349 } 2350 2351 } 2352 2353 2359 void planForExpression(Expression exp) { 2360 if (exp == null) { 2361 return; 2362 } 2363 2364 Object ob = exp.last(); 2365 if (ob instanceof Operator && ((Operator) ob).isLogical()) { 2366 Operator last_op = (Operator) ob; 2367 2368 if (last_op.is("or")) { 2369 Expression[] exps = exp.split(); 2372 2375 setCachePoints(); 2377 2378 QueryTableSetPlanner left_planner = copy(); 2380 QueryTableSetPlanner right_planner = copy(); 2381 2382 left_planner.planForExpression(exps[0]); 2384 right_planner.planForExpression(exps[1]); 2385 2386 int left_sz = left_planner.table_list.size(); 2391 int right_sz = right_planner.table_list.size(); 2392 if (left_sz != right_sz || 2393 left_planner.hasJoinOccured() || 2394 right_planner.hasJoinOccured()) { 2395 left_planner.naturalJoinAll(); 2397 right_planner.naturalJoinAll(); 2398 } 2399 2400 ArrayList left_table_list = left_planner.table_list; 2402 ArrayList right_table_list = right_planner.table_list; 2403 int sz = left_table_list.size(); 2404 2405 ArrayList left_join_list = new ArrayList (); 2408 ArrayList right_join_list = new ArrayList (); 2409 for (int i = 0; i < sz; ++i) { 2410 PlanTableSource left_plan = 2411 (PlanTableSource) left_table_list.get(i); 2412 PlanTableSource right_plan = 2413 (PlanTableSource) right_table_list.get(i); 2414 if (left_plan.isUpdated() || right_plan.isUpdated()) { 2415 left_join_list.add(left_plan); 2416 right_join_list.add(right_plan); 2417 } 2418 } 2419 2420 left_planner.joinAllPlansToSingleSource(left_join_list); 2422 right_planner.joinAllPlansToSingleSource(right_join_list); 2423 2424 left_table_list = left_planner.table_list; 2426 right_table_list = right_planner.table_list; 2427 sz = left_table_list.size(); 2428 2429 ArrayList new_table_list = new ArrayList (sz); 2430 2431 for (int i = 0; i < sz; ++i) { 2432 PlanTableSource left_plan = 2433 (PlanTableSource) left_table_list.get(i); 2434 PlanTableSource right_plan = 2435 (PlanTableSource) right_table_list.get(i); 2436 2437 PlanTableSource new_plan; 2438 2439 if (left_plan.isUpdated() || right_plan.isUpdated()) { 2441 2442 2445 QueryPlanNode node = new QueryPlan.LogicalUnionNode( 2448 left_plan.getPlan(), right_plan.getPlan()); 2449 2450 left_plan.updatePlan(node); 2452 2453 new_plan = left_plan; 2454 } 2455 else { 2456 new_plan = left_plan; 2460 } 2461 2462 new_table_list.add(new_plan); 2464 2465 } 2466 2467 table_list = new_table_list; 2469 2470 } 2471 2472 else if (last_op.is("and")) { 2473 ArrayList and_list = new ArrayList (); 2476 and_list = createAndList(and_list, exp); 2477 2478 planForExpressionList(and_list); 2479 2480 } 2481 2482 else { 2483 throw new RuntimeException ("Unknown logical operator: " + ob); 2484 } 2485 2486 } 2487 else { 2488 ArrayList exp_list = new ArrayList (1); 2490 exp_list.add(exp); 2491 planForExpressionList(exp_list); 2492 } 2493 2494 } 2495 2496 2501 QueryPlanNode logicalEvaluate(Expression exp) { 2502 2503 2505 if (exp == null) { 2506 naturalJoinAll(); 2508 return getSingleTableSource().getPlan(); 2510 } 2511 2512 planForExpression(exp); 2514 2515 naturalJoinAll(); 2517 2518 return getSingleTableSource().getPlan(); 2520 } 2521 2522 2523 2524 2525 2533 private ArrayList createAndList(ArrayList list, Expression exp) { 2534 return exp.breakByOperator(list, "and"); 2535 } 2536 2537 2540 QueryPlanNode planSearchExpression(SearchExpression search_expression) { 2541 planAllOuterJoins(); 2543 2544 QueryPlanNode node = 2545 logicalEvaluate(search_expression.getFromExpression()); 2546 return node; 2547 } 2548 2549 2552 private QueryTableSetPlanner copy() { 2553 QueryTableSetPlanner copy = new QueryTableSetPlanner(); 2554 int sz = table_list.size(); 2555 for (int i = 0; i < sz; ++i) { 2556 copy.table_list.add(((PlanTableSource) table_list.get(i)).copy()); 2557 } 2558 for (int i = 0; i < sz; ++i) { 2560 PlanTableSource src = (PlanTableSource) table_list.get(i); 2561 PlanTableSource mod = (PlanTableSource) copy.table_list.get(i); 2562 if (src.left_plan != null) { 2564 int n = indexOfPlanTableSource(src.left_plan); 2565 mod.setLeftJoinInfo((PlanTableSource) copy.table_list.get(n), 2566 src.left_join_type, src.left_on_expr); 2567 } 2568 if (src.right_plan != null) { 2570 int n = indexOfPlanTableSource(src.right_plan); 2571 mod.setRightJoinInfo((PlanTableSource) copy.table_list.get(n), 2572 src.right_join_type, src.right_on_expr); 2573 } 2574 } 2575 2576 return copy; 2577 } 2578 2579 void printDebugInfo() { 2580 StringBuffer buf = new StringBuffer (); 2581 buf.append("PLANNER:\n"); 2582 for (int i = 0; i < table_list.size(); ++i) { 2583 buf.append("TABLE " + i + "\n"); 2584 ((PlanTableSource) table_list.get(i)).getPlan().debugString(2, buf); 2585 buf.append("\n"); 2586 } 2587 System.out.println(buf); 2588 } 2589 2590 2591 } 2592 2593 2596 private static class PlanTableSource { 2597 2598 2601 private QueryPlanNode plan; 2602 2603 2607 private final Variable[] var_list; 2608 2609 2612 private final String [] unique_names; 2613 2614 2618 private boolean is_updated; 2619 2620 2625 PlanTableSource left_plan, right_plan; 2626 int left_join_type, right_join_type; 2627 Expression left_on_expr, right_on_expr; 2628 2629 2630 2633 public PlanTableSource(QueryPlanNode plan, Variable[] var_list, 2634 String [] table_unique_names) { 2635 this.plan = plan; 2636 this.var_list = var_list; 2637 this.unique_names = table_unique_names; 2638 left_join_type = -1; 2639 right_join_type = -1; 2640 is_updated = false; 2641 } 2642 2643 2646 void setLeftJoinInfo(PlanTableSource left_plan, 2647 int join_type, Expression on_expr) { 2648 this.left_plan = left_plan; 2649 this.left_join_type = join_type; 2650 this.left_on_expr = on_expr; 2651 } 2652 2653 2656 void setRightJoinInfo(PlanTableSource right_plan, 2657 int join_type, Expression on_expr) { 2658 this.right_plan = right_plan; 2659 this.right_join_type = join_type; 2660 this.right_on_expr = on_expr; 2661 } 2662 2663 2669 void setJoinInfoMergedBetween( 2670 PlanTableSource left, PlanTableSource right) { 2671 2672 if (left.right_plan != right) { 2673 if (left.right_plan != null) { 2674 setRightJoinInfo(left.right_plan, 2675 left.right_join_type, left.right_on_expr); 2676 right_plan.left_plan = this; 2677 } 2678 if (right.left_plan != null) { 2679 setLeftJoinInfo(right.left_plan, 2680 right.left_join_type, right.left_on_expr); 2681 left_plan.right_plan = this; 2682 } 2683 } 2684 if (left.left_plan != right) { 2685 if (left_plan == null && left.left_plan != null) { 2686 setLeftJoinInfo(left.left_plan, 2687 left.left_join_type, left.left_on_expr); 2688 left_plan.right_plan = this; 2689 } 2690 if (right_plan == null && right.right_plan != null) { 2691 setRightJoinInfo(right.right_plan, 2692 right.right_join_type, right.right_on_expr); 2693 right_plan.left_plan = this; 2694 } 2695 } 2696 2697 } 2698 2699 2702 public boolean containsVariable(Variable v) { 2703 for (int i = 0; i < var_list.length; ++i) { 2705 if (var_list[i].equals(v)) { 2707 return true; 2708 } 2709 } 2710 return false; 2711 } 2712 2713 2717 public boolean containsUniqueKey(String name) { 2718 for (int i = 0; i < unique_names.length; ++i) { 2719 if (unique_names[i].equals(name)) { 2720 return true; 2721 } 2722 } 2723 return false; 2724 } 2725 2726 2729 public void setUpdated() { 2730 is_updated = true; 2731 } 2732 2733 2736 public void updatePlan(QueryPlanNode node) { 2737 plan = node; 2738 setUpdated(); 2739 } 2740 2741 2744 public QueryPlanNode getPlan() { 2745 return plan; 2746 } 2747 2748 2751 public boolean isUpdated() { 2752 return is_updated; 2753 } 2754 2755 2758 public PlanTableSource copy() { 2759 return new PlanTableSource(plan, var_list, unique_names); 2760 } 2761 2762 } 2763 2764 2772 static abstract class ExpressionPlan implements Comparable { 2773 2774 2778 private float optimizable_value; 2779 2780 2783 public void setOptimizableValue(float v) { 2784 optimizable_value = v; 2785 } 2786 2787 2790 public float getOptimizableValue() { 2791 return optimizable_value; 2792 } 2793 2794 2797 public abstract void addToPlanTree(); 2798 2799 public int compareTo(Object ob) { 2800 ExpressionPlan dest_plan = (ExpressionPlan) ob; 2801 float dest_val = dest_plan.optimizable_value; 2802 if (optimizable_value > dest_val) { 2803 return 1; 2804 } 2805 else if (optimizable_value < dest_val) { 2806 return -1; 2807 } 2808 else { 2809 return 0; 2810 } 2811 } 2812 2813 } 2814 2815} 2816 | Popular Tags |