1 15 package org.josql; 16 17 import java.io.File ; 18 import java.io.StringReader ; 19 import java.io.BufferedReader ; 20 21 import java.util.Map ; 22 import java.util.HashMap ; 23 import java.util.SortedMap ; 24 import java.util.LinkedHashMap ; 25 import java.util.List ; 26 import java.util.ArrayList ; 27 import java.util.StringTokenizer ; 28 import java.util.Iterator ; 29 import java.util.Collections ; 30 import java.util.Arrays ; 31 import java.util.Comparator ; 32 import java.util.Set ; 33 import java.util.LinkedHashSet ; 34 import java.util.Collection ; 35 36 import org.josql.parser.JoSQLParser; 37 38 import org.josql.expressions.*; 39 40 import org.josql.functions.*; 41 42 import org.josql.internal.*; 43 44 import org.josql.events.*; 45 46 99 public class Query 100 { 101 102 public static String QUERY_BIND_VAR_NAME = "_query"; 103 public static String PARENT_BIND_VAR_NAME = "_parent"; 104 public static String CURR_OBJ_VAR_NAME = "_currobj"; 105 public static String ALL_OBJS_VAR_NAME = "_allobjs"; 106 public static String GRPBY_OBJ_VAR_NAME = "_grpby"; 107 public static String GRPBY_OBJ_VAR_NAME_SYNONYM = "_groupby"; 108 public static final String INT_BIND_VAR_PREFIX = "^^^"; 109 110 public static final String ALL = "ALL"; 111 public static final String RESULTS = "RESULTS"; 112 public static final String GROUP_BY_RESULTS = "GROUP_BY_RESULTS"; 113 public static final String WHERE_RESULTS = "WHERE_RESULTS"; 114 public static final String HAVING_RESULTS = "HAVING_RESULTS"; 115 116 public static final String ORDER_BY_ASC = "ASC"; 117 public static final String ORDER_BY_DESC = "DESC"; 118 119 public static final List nullQueryList = new ArrayList (); 120 121 static 122 { 123 124 Query.nullQueryList.add (new Object ()); 125 126 } 127 128 private List bfhs = new ArrayList (); 129 private Map bfhsMap = new HashMap (); 130 131 private char wildcardChar = '%'; 132 133 private Map aliases = new HashMap (); 134 private List groupBys = null; 135 private Comparator orderByComp = null; 136 private Comparator groupOrderByComp = null; 137 private Grouper grouper = null; 138 private List orderBys = null; 139 private List groupOrderBys = null; 140 private List cols = null; 141 private boolean retObjs = false; 142 private Expression where = null; 143 private Expression having = null; 144 private Map bindVars = null; 145 private String query = null; 146 private boolean wantTimings = false; 147 private List functionHandlers = null; 148 private int anonVarIndex = 1; 149 private Expression from = null; 150 private Class objClass = null; 151 private Limit limit = null; 152 private Limit groupByLimit = null; 153 private Map executeOn = null; 154 private boolean isParsed = false; 155 private boolean distinctResults = false; 156 private ClassLoader classLoader = null; 157 private Query parent = null; 158 private Map listeners = new HashMap (); 159 160 private transient Object currentObject = null; 162 private transient List allObjects = null; 163 private transient List currGroupBys = null; 164 165 private QueryResults qd = null; 166 167 172 public Expression getWhereClause () 173 { 174 175 return this.where; 176 177 } 178 179 184 public Expression getHavingClause () 185 { 186 187 return this.having; 188 189 } 190 191 196 public Comparator getOrderByComparator () 197 { 198 199 return this.orderByComp; 200 201 } 202 203 public FunctionHandler getFunctionHandler (String id) 204 { 205 206 if (this.parent != null) 207 { 208 209 return this.parent.getFunctionHandler (id); 210 211 } 212 213 return (FunctionHandler) this.bfhsMap.get (id); 214 215 } 216 217 private void initFunctionHandlers () 218 { 219 220 FunctionHandler o = new CollectionFunctions (); 221 o.setQuery (this); 222 223 this.bfhsMap.put (CollectionFunctions.HANDLER_ID, 224 o); 225 226 this.bfhs.add (o); 227 228 o = new StringFunctions (); 229 o.setQuery (this); 230 231 this.bfhsMap.put (StringFunctions.HANDLER_ID, 232 o); 233 234 this.bfhs.add (o); 235 236 o = new ConversionFunctions (); 237 o.setQuery (this); 238 239 this.bfhsMap.put (ConversionFunctions.HANDLER_ID, 240 o); 241 242 this.bfhs.add (o); 243 244 o = new FormattingFunctions (); 245 o.setQuery (this); 246 247 this.bfhsMap.put (FormattingFunctions.HANDLER_ID, 248 o); 249 250 this.bfhs.add (o); 251 252 o = new GroupingFunctions (); 253 o.setQuery (this); 254 255 this.bfhsMap.put (GroupingFunctions.HANDLER_ID, 256 o); 257 258 this.bfhs.add (o); 259 260 o = new MiscellaneousFunctions (); 261 o.setQuery (this); 262 263 this.bfhsMap.put (MiscellaneousFunctions.HANDLER_ID, 264 o); 265 266 this.bfhs.add (o); 267 268 } 269 270 public Map getExecuteOnFunctions () 271 { 272 273 return this.executeOn; 274 275 } 276 277 public void setExecuteOnFunctions (Map ex) 278 { 279 280 this.executeOn = ex; 281 282 } 283 284 public String getAnonymousBindVariableName () 285 { 286 287 if (this.parent != null) 288 { 289 290 return this.parent.getAnonymousBindVariableName (); 291 292 } 293 294 String n = Query.INT_BIND_VAR_PREFIX + this.anonVarIndex; 295 296 this.anonVarIndex++; 297 298 return n; 299 300 } 301 302 public List getDefaultFunctionHandlers () 303 { 304 305 if (this.parent != null) 306 { 307 308 return this.parent.getDefaultFunctionHandlers (); 309 310 } 311 312 return new ArrayList (this.bfhs); 313 314 } 315 316 public List getFunctionHandlers () 317 { 318 319 if (this.parent != null) 320 { 321 322 return this.parent.getFunctionHandlers (); 323 324 } 325 326 return this.functionHandlers; 327 328 } 329 330 public void addFunctionHandler (Object o) 331 { 332 333 if (this.parent != null) 334 { 335 336 this.parent.addFunctionHandler (o); 337 338 } 339 340 if (this.functionHandlers == null) 341 { 342 343 this.functionHandlers = new ArrayList (); 344 345 } 346 347 if (o instanceof FunctionHandler) 348 { 349 350 FunctionHandler fh = (FunctionHandler) o; 351 352 fh.setQuery (this); 353 354 } 355 356 this.functionHandlers.add (o); 357 358 } 359 360 public void setFrom (Expression exp) 361 { 362 363 this.from = exp; 364 365 } 366 367 public Expression getFrom () 368 { 369 370 return this.from; 371 372 } 373 374 public void setClassName (String n) 375 { 376 377 ConstantExpression ce = new ConstantExpression (); 378 this.from = ce; 379 ce.setValue (n); 380 381 } 382 383 public void setOrderByColumns (List cols) 384 { 385 386 this.orderBys = cols; 387 388 } 389 390 public void setGroupByLimit (Limit g) 391 { 392 393 this.groupByLimit = g; 394 395 } 396 397 public void setGroupByOrderColumns (List cols) 398 { 399 400 this.groupOrderBys = cols; 401 402 } 403 404 public List getGroupByColumns () 405 { 406 407 return this.groupBys; 408 409 } 410 411 public void setGroupByColumns (List cols) 412 { 413 414 this.groupBys = cols; 415 416 } 417 418 public List getColumns () 419 { 420 421 return this.cols; 422 423 } 424 425 public void setColumns (List cols) 426 { 427 428 this.cols = cols; 429 430 } 431 432 public void setHaving (Expression be) 433 { 434 435 this.having = be; 436 437 } 438 439 public void setWhere (Expression be) 440 { 441 442 this.where = be; 443 444 } 445 446 public Query () 447 { 448 449 this.initFunctionHandlers (); 450 451 } 452 453 public void setWantTimings (boolean v) 454 { 455 456 this.wantTimings = v; 457 458 } 459 460 protected void addTiming (String id, 461 double time) 462 { 463 464 if (this.wantTimings) 465 { 466 467 if (this.qd == null) 468 { 469 470 return; 471 472 } 473 474 if (this.qd.timings == null) 475 { 476 477 this.qd.timings = new LinkedHashMap (); 478 479 } 480 481 this.qd.timings.put (id, 482 new Double (time)); 483 484 } 485 486 } 487 488 public Object getVariable (int index) 489 { 490 491 if (this.parent != null) 492 { 493 494 return this.parent.getVariable (index); 495 496 } 497 498 return this.getVariable (Query.INT_BIND_VAR_PREFIX + index); 499 500 } 501 502 public Class getVariableClass (String name) 503 { 504 505 String n = name.toLowerCase (); 506 507 if (n.equals (Query.QUERY_BIND_VAR_NAME)) 508 { 509 510 return Query.class; 512 513 } 514 515 if (n.equals (Query.PARENT_BIND_VAR_NAME)) 516 { 517 518 return Query.class; 520 521 } 522 523 if (n.equals (Query.CURR_OBJ_VAR_NAME)) 524 { 525 526 return this.objClass; 528 529 } 530 531 if (n.equals (Query.ALL_OBJS_VAR_NAME)) 532 { 533 534 return List .class; 536 537 } 538 539 if (this.bindVars == null) 540 { 541 542 return Object .class; 543 544 } 545 546 if (this.parent != null) 547 { 548 549 return this.parent.getVariableClass (n); 550 551 } 552 553 Object v = (Object ) this.bindVars.get (n); 554 555 if (v == null) 556 { 557 558 return Object .class; 559 560 } 561 562 return v.getClass (); 563 564 } 565 566 public Object getGroupByVariable (int ind) 567 { 568 569 if (this.currGroupBys != null) 571 { 572 573 return this.currGroupBys.get (ind - 1); 574 575 } 576 577 return null; 578 579 } 580 581 public Object getVariable (String name) 582 { 583 584 String n = name.toLowerCase (); 585 586 if (n.equals (Query.QUERY_BIND_VAR_NAME)) 587 { 588 589 return this; 591 592 } 593 594 if (n.equals (Query.PARENT_BIND_VAR_NAME)) 595 { 596 597 return this.parent; 599 600 } 601 602 if (n.equals (Query.CURR_OBJ_VAR_NAME)) 603 { 604 605 return this.currentObject; 607 608 } 609 610 if (n.equals (Query.ALL_OBJS_VAR_NAME)) 611 { 612 613 return this.allObjects; 615 616 } 617 618 if (this.bindVars == null) 619 { 620 621 return null; 622 623 } 624 625 if (this.parent != null) 626 { 627 628 return this.parent.getVariable (name); 629 630 } 631 632 return this.bindVars.get (n); 633 634 } 635 636 public void setVariable (String name, 637 Object v) 638 { 639 640 if (this.parent != null) 641 { 642 643 this.parent.setVariable (name, 644 v); 645 646 return; 647 648 } 649 650 if (this.bindVars == null) 651 { 652 653 this.bindVars = new HashMap (); 654 655 } 656 657 this.bindVars.put (name.toLowerCase (), 658 v); 659 660 } 661 662 public void setVariable (int index, 663 Object v) 664 { 665 666 if (this.parent != null) 667 { 668 669 this.parent.setVariable (index, 670 v); 671 672 return; 673 674 } 675 676 this.setVariable (Query.INT_BIND_VAR_PREFIX + index, 677 v); 678 679 } 680 681 public Map getVariables () 682 { 683 684 if (this.parent != null) 685 { 686 687 return this.parent.getVariables (); 688 689 } 690 691 return this.bindVars; 692 693 } 694 695 public boolean isWhereTrue (Object o) 696 throws QueryExecutionException 697 { 698 699 if (this.where == null) 700 { 701 702 return true; 704 705 } 706 707 return this.where.isTrue (o, 708 this); 709 710 } 711 712 public void setVariables (Map bVars) 713 { 714 715 if (this.parent != null) 716 { 717 718 this.parent.setVariables (bVars); 719 720 return; 721 722 } 723 724 this.bindVars = bVars; 725 726 } 727 728 738 public void doExecuteOn (List l, 739 String t) 740 throws QueryExecutionException 741 { 742 743 if (!this.isParsed) 744 { 745 746 throw new QueryExecutionException ("Query has not been initialised."); 747 748 } 749 750 if (this.executeOn != null) 751 { 752 753 this.allObjects = l; 755 756 long s = System.currentTimeMillis (); 757 758 List fs = (List ) this.executeOn.get (t); 759 760 if (fs != null) 761 { 762 763 int si = fs.size (); 765 766 for (int i = 0; i < si; i++) 767 { 768 769 AliasedExpression f = (AliasedExpression) fs.get (i); 770 771 Object o = f.getValue (null, 772 this); 773 774 String af = f.getAlias (); 775 776 if (af != null) 777 { 778 779 this.setSaveValue (af, 780 o); 781 782 } 783 784 } 785 786 this.addTiming ("Total time to execute: " + si + " expression(s) on " + t + " objects", 787 System.currentTimeMillis () - s); 788 789 } 790 791 } 792 793 } 794 795 803 public void clearResults () 804 { 805 806 this.qd = null; 807 808 this.currentObject = null; 809 this.allObjects = null; 810 811 } 812 813 820 public QueryResults execute (List objs) 821 throws QueryExecutionException 822 { 823 824 if ((objs == null) 825 && 826 (this.objClass != null) 827 ) 828 { 829 830 throw new QueryExecutionException ("List of objects must be non-null when an object class is specified."); 831 832 } 833 834 this.qd = new QueryResults (); 835 836 if ((this.objClass == null) 837 && 838 (objs == null) 839 ) 840 { 841 842 objs = Query.nullQueryList; 843 844 } 845 846 this.allObjects = objs; 847 848 long s = System.currentTimeMillis (); 849 850 if (this.executeOn != null) 853 { 854 855 this.doExecuteOn (objs, 856 Query.ALL); 857 858 } 859 860 s = System.currentTimeMillis (); 861 862 if (this.where != null) 863 { 864 865 int si = objs.size (); 866 867 this.qd.whereResults = new ArrayList (si / 2); 873 874 for (int i = 0; i < si; i++) 875 { 876 877 Object o = objs.get (i); 878 879 this.currentObject = o; 880 881 boolean res = this.where.isTrue (o, 882 this); 883 884 if (res) 885 { 886 887 this.qd.whereResults.add (o); 888 889 } 890 891 } 892 893 } else { 894 895 this.qd.whereResults = objs; 897 898 } 899 900 double wet = (double) System.currentTimeMillis () - (double) s; 901 902 this.addTiming ("Total time to execute Where clause on all objects", 903 wet); 904 this.addTiming ("Where took average over: " + objs.size () + " objects", 905 wet / (double) objs.size ()); 906 907 this.allObjects = this.qd.whereResults; 908 909 this.qd.results = this.qd.whereResults; 911 912 if (this.executeOn != null) 915 { 916 917 this.doExecuteOn (this.qd.results, 918 Query.RESULTS); 919 920 } 921 922 if (this.having != null) 924 { 925 926 int si = this.qd.results.size (); 927 928 this.qd.havingResults = new ArrayList (si); 929 930 for (int i = 0; i < si; i++) 931 { 932 933 Object o = this.qd.results.get (i); 934 935 this.currentObject = o; 936 937 if (this.having.isTrue (o, 938 this)) 939 { 940 941 this.qd.havingResults.add (o); 942 943 } 944 945 } 946 947 this.qd.results = this.qd.havingResults; 948 949 this.allObjects = this.qd.results; 951 952 } 953 954 if (this.grouper != null) 956 { 957 958 try 960 { 961 962 s = System.currentTimeMillis (); 963 964 Map mres = this.grouper.group (this.qd.results); 965 966 this.qd.groupByResults = mres; 967 968 List grpBys = new ArrayList (mres.keySet ()); 969 970 if (this.groupOrderByComp != null) 972 { 973 974 Map origSvs = this.qd.saveValues; 975 976 Collections.sort (grpBys, 977 this.groupOrderByComp); 978 979 this.qd.saveValues = origSvs; 981 982 GroupByExpressionComparator lec = (GroupByExpressionComparator) this.groupOrderByComp; 983 984 if (lec.getException () != null) 985 { 986 987 throw new QueryExecutionException ("Unable to order group bys, remember that the current object here is a java.util.List, not the class defined in the FROM clause, you may need to use the org.josq.functions.CollectionFunctions.get(java.util.List,Number) function to get access to the relevant value from the List.", 988 lec.getException ()); 989 990 } 991 992 lec.clearCache (); 993 994 } 995 996 if (this.groupByLimit != null) 998 { 999 1000 s = System.currentTimeMillis (); 1001 1002 grpBys = this.groupByLimit.getSubList (grpBys, 1003 this); 1004 1005 this.addTiming ("Total time to limit group by results size", 1006 System.currentTimeMillis () - s); 1007 1008 } 1009 1010 long t = System.currentTimeMillis (); 1011 1012 this.addTiming ("Group operation took", 1013 (double) (t - s)); 1014 1015 s = System.currentTimeMillis (); 1016 1017 if ((this.orderByComp != null) 1019 || 1020 (!this.retObjs) 1021 ) 1022 { 1023 1024 Map origSvs = this.qd.saveValues; 1025 1026 Map nres = new LinkedHashMap (); 1027 1028 int gs = grpBys.size (); 1029 1030 for (int i = 0; i < gs; i++) 1031 { 1032 1033 List l = (List ) grpBys.get (i); 1034 1035 List lr = (List ) mres.get (l); 1036 1037 this.allObjects = lr; 1038 this.currGroupBys = l; 1039 1040 if (this.qd.groupBySaveValues == null) 1042 { 1043 1044 this.qd.groupBySaveValues = new HashMap (); 1045 1046 } 1047 1048 this.qd.saveValues = new HashMap (); 1049 1050 this.qd.groupBySaveValues.put (l, 1051 this.qd.saveValues); 1052 1053 this.doExecuteOn (lr, 1055 Query.GROUP_BY_RESULTS); 1056 1057 if ((lr.size () > 1) 1059 && 1060 (this.orderByComp != null) 1061 ) 1062 { 1063 1064 Collections.sort (lr, 1065 this.orderByComp); 1066 1067 ListExpressionComparator lec = (ListExpressionComparator) this.orderByComp; 1068 1069 if (lec.getException () != null) 1070 { 1071 1072 throw new QueryExecutionException ("Unable to order group by results", 1073 lec.getException ()); 1074 1075 } 1076 1077 lec.clearCache (); 1078 1079 } 1080 1081 if (!this.retObjs) 1082 { 1083 1084 Collection res = null; 1086 1087 if (!this.distinctResults) 1088 { 1089 1090 res = new ArrayList (); 1091 1092 } else { 1093 1094 res = new LinkedHashSet (); 1095 1096 } 1097 1098 this.getColumnValues (lr, 1099 res); 1100 1101 if (this.distinctResults) 1102 { 1103 1104 lr = new ArrayList (res); 1105 1106 } else { 1107 1108 lr = (List ) res; 1109 1110 } 1111 1112 } else { 1113 1114 if (this.distinctResults) 1115 { 1116 1117 this.qd.results = ((CollectionFunctions) this.getFunctionHandler (CollectionFunctions.HANDLER_ID)).unique (this.qd.results); 1118 1119 } 1120 1121 } 1122 1123 if (this.limit != null) 1124 { 1125 1126 lr = this.limit.getSubList (lr, 1127 this); 1128 1129 } 1130 1131 nres.put (l, 1132 lr); 1133 1134 } 1135 1136 this.qd.groupByResults = nres; 1137 1138 this.qd.saveValues = origSvs; 1140 1141 } 1142 1143 t = System.currentTimeMillis (); 1144 1145 this.addTiming ("Group column collection and sort took", 1146 (double) (t - s)); 1147 1148 this.qd.results = grpBys; 1149 1150 return this.qd; 1151 1152 } catch (Exception e) { 1153 1154 throw new QueryExecutionException ("Unable to perform group by operation", 1155 e); 1156 1157 } 1158 1159 } 1160 1161 if ((this.qd.results.size () > 1) 1163 && 1164 (this.orderByComp != null) 1165 ) 1166 { 1167 1168 s = System.currentTimeMillis (); 1169 1170 Collections.sort (this.qd.results, 1174 this.orderByComp); 1175 1176 this.addTiming ("Total time to order results", 1177 System.currentTimeMillis () - s); 1178 1179 } 1180 1181 if (this.orderByComp != null) 1182 { 1183 1184 ListExpressionComparator lec = (ListExpressionComparator) this.orderByComp; 1185 1186 if (lec.getException () != null) 1187 { 1188 1189 throw new QueryExecutionException ("Unable to order results", 1190 lec.getException ()); 1191 1192 } 1193 1194 lec.clearCache (); 1195 1196 } 1197 1198 if (this.limit != null) 1200 { 1201 1202 s = System.currentTimeMillis (); 1203 1204 this.qd.results = this.limit.getSubList (this.qd.results, 1205 this); 1206 1207 this.addTiming ("Total time to limit results size", 1208 System.currentTimeMillis () - s); 1209 1210 } 1211 1212 boolean retNewObjs = false; 1213 1214 if (!this.retObjs) 1216 { 1217 1218 if (this.cols.size () == 1) 1219 { 1220 1221 SelectItemExpression sei = (SelectItemExpression) this.cols.get (0); 1222 1223 if (sei.getExpression () instanceof NewObjectExpression) 1224 { 1225 1226 retNewObjs = true; 1227 1228 } 1229 1230 } 1231 1232 } 1233 1234 if ((!this.retObjs) 1237 && 1238 (!retNewObjs) 1239 ) 1240 { 1241 1242 s = System.currentTimeMillis (); 1243 1244 Collection resC = null; 1245 1246 if (!this.distinctResults) 1247 { 1248 1249 resC = new ArrayList (this.qd.results.size ()); 1250 1251 } else { 1252 1253 resC = new LinkedHashSet (this.qd.results.size ()); 1254 1255 } 1256 1257 this.getColumnValues (this.qd.results, 1259 resC); 1260 1261 if (this.distinctResults) 1262 { 1263 1264 this.qd.results = new ArrayList (resC); 1265 1266 } else { 1267 1268 this.qd.results = (List ) resC; 1269 1270 } 1271 1272 this.addTiming ("Collection of results took", 1273 (double) (System.currentTimeMillis () - s)); 1274 1275 } else { 1276 1277 if (this.retObjs) 1278 { 1279 1280 if (this.distinctResults) 1281 { 1282 1283 s = System.currentTimeMillis (); 1284 1285 this.qd.results = ((CollectionFunctions) this.getFunctionHandler (CollectionFunctions.HANDLER_ID)).unique (this.qd.results); 1286 1287 this.addTiming ("Collecting unique results took", 1288 (double) (System.currentTimeMillis () - s)); 1289 1290 } 1291 1292 } 1293 1294 if (retNewObjs) 1296 { 1297 1298 this.qd.results = this.getNewObjectSingleColumnValues (this.qd.results); 1299 1300 } 1301 1302 } 1303 1304 try 1305 { 1306 1307 return this.qd; 1308 1309 } finally { 1310 1311 this.clearResults (); 1313 1314 } 1315 1316 } 1317 1318 public void setCurrentGroupByObjects (List objs) 1319 { 1320 1321 this.currGroupBys = objs; 1322 1323 } 1324 1325 public List getAllObjects () 1326 { 1327 1328 return this.allObjects; 1329 1330 } 1331 1332 public void setAllObjects (List objs) 1333 { 1334 1335 this.allObjects = objs; 1336 1337 } 1338 1339 public void setCurrentObject (Object o) 1340 { 1341 1342 this.currentObject = o; 1343 1344 } 1345 1346 public Object getCurrentObject () 1347 { 1348 1349 return this.currentObject; 1350 1351 } 1352 1353 private void getColumnValues (List res, 1354 Collection rs) 1355 throws QueryExecutionException 1356 { 1357 1358 int s = res.size (); 1359 1360 int cs = this.cols.size (); 1361 1362 boolean addItems = false; 1363 1364 for (int i = 0; i < s; i++) 1365 { 1366 1367 Object o = res.get (i); 1368 1369 this.currentObject = o; 1370 1371 List sRes = new ArrayList (cs); 1372 1373 for (int j = 0; j < cs; j++) 1374 { 1375 1376 SelectItemExpression v = (SelectItemExpression) this.cols.get (j); 1377 1378 try 1379 { 1380 1381 if (v.isAddItemsFromCollectionOrMap ()) 1382 { 1383 1384 addItems = true; 1385 1386 } 1387 1388 Object ov = v.getValue (o, 1390 this); 1391 1392 if (addItems) 1393 { 1394 1395 rs.addAll (v.getAddItems (ov)); 1396 1397 } else { 1398 1399 sRes.add (ov); 1400 1401 } 1402 1403 this.currentObject = o; 1406 1407 } catch (Exception e) { 1408 1409 throw new QueryExecutionException ("Unable to get value for column: " + 1410 j + 1411 " for: " + 1412 v.toString () + 1413 " from result: " + 1414 i + 1415 " (" + 1416 o + 1417 ")", 1418 e); 1419 1420 } 1421 1422 } 1423 1424 if (!addItems) 1425 { 1426 1427 rs.add (sRes); 1428 1429 } 1430 1431 } 1432 1433 } 1434 1435 private List getNewObjectSingleColumnValues (List rows) 1436 throws QueryExecutionException 1437 { 1438 1439 int s = rows.size (); 1440 1441 SelectItemExpression nsei = (SelectItemExpression) this.cols.get (0); 1442 1443 List res = new ArrayList (s); 1444 1445 for (int i = 0; i < s; i++) 1446 { 1447 1448 Object o = rows.get (i); 1449 1450 this.currentObject = o; 1451 1452 try 1453 { 1454 1455 res.add (nsei.getValue (o, 1456 this)); 1457 1458 this.currentObject = o; 1461 1462 } catch (Exception e) { 1463 1464 throw new QueryExecutionException ("Unable to get value for column: " + 1465 1 + 1466 " for: " + 1467 nsei.toString () + 1468 " from result: " + 1469 i + 1470 " (" + 1471 o + 1472 ")", 1473 e); 1474 1475 } 1476 1477 } 1478 1479 return res; 1480 1481 } 1482 1483 public void setSaveValues (Map s) 1484 { 1485 1486 if (this.parent != null) 1487 { 1488 1489 this.parent.qd.saveValues.putAll (s); 1490 1491 return; 1492 1493 } 1494 1495 this.qd.saveValues = s; 1496 1497 } 1498 1499 public void setSaveValue (Object id, 1500 Object value) 1501 { 1502 1503 if (this.parent != null) 1504 { 1505 1506 this.parent.setSaveValue (id, 1507 value); 1508 1509 return; 1510 1511 } 1512 1513 if (this.qd == null) 1514 { 1515 1516 return; 1517 1518 } 1519 1520 if (id instanceof String ) 1521 { 1522 1523 id = ((String ) id).toLowerCase (); 1524 1525 } 1526 1527 Object old = this.qd.saveValues.get (id); 1528 1529 this.qd.saveValues.put (id, 1530 value); 1531 1532 if (old != null) 1533 { 1534 1535 this.fireSaveValueChangedEvent (id, 1536 old, 1537 value); 1538 1539 } 1540 1541 } 1542 1543 protected void fireSaveValueChangedEvent (Object id, 1544 Object from, 1545 Object to) 1546 { 1547 1548 List l = (List ) this.listeners.get ("svs"); 1549 1550 if ((l == null) 1551 || 1552 (l.size () == 0) 1553 ) 1554 { 1555 1556 return; 1557 1558 } 1559 1560 SaveValueChangedEvent svce = new SaveValueChangedEvent (this, 1561 id.toString ().toLowerCase (), 1562 from, 1563 to); 1564 1565 for (int i = 0; i < l.size (); i++) 1566 { 1567 1568 SaveValueChangedListener svcl = (SaveValueChangedListener) l.get (i); 1569 1570 svcl.saveValueChanged (svce); 1571 1572 } 1573 1574 } 1575 1576 protected void fireBindVariableChangedEvent (String name, 1577 Object from, 1578 Object to) 1579 { 1580 1581 List l = (List ) this.listeners.get ("bvs"); 1582 1583 if ((l == null) 1584 || 1585 (l.size () == 0) 1586 ) 1587 { 1588 1589 return; 1590 1591 } 1592 1593 BindVariableChangedEvent bvce = new BindVariableChangedEvent (this, 1594 name, 1595 from, 1596 to); 1597 1598 for (int i = 0; i < l.size (); i++) 1599 { 1600 1601 BindVariableChangedListener bvcl = (BindVariableChangedListener) l.get (i); 1602 1603 bvcl.bindVariableChanged (bvce); 1604 1605 } 1606 1607 } 1608 1609 1616 public Object getGroupBySaveValue (Object id, 1617 List gbs) 1618 { 1619 1620 if (this.parent != null) 1621 { 1622 1623 return this.getGroupBySaveValue (id, 1624 gbs); 1625 1626 } 1627 1628 Map m = this.getGroupBySaveValues (gbs); 1629 1630 if (m == null) 1631 { 1632 1633 return null; 1634 1635 } 1636 1637 return m.get (id); 1638 1639 } 1640 1641 public Map getGroupBySaveValues (List gbs) 1642 { 1643 1644 if (this.parent != null) 1645 { 1646 1647 return this.parent.getGroupBySaveValues (gbs); 1648 1649 } 1650 1651 if ((this.qd == null) 1652 || 1653 (this.qd.groupBySaveValues == null) 1654 ) 1655 { 1656 1657 return null; 1658 1659 } 1660 1661 return (Map ) this.qd.groupBySaveValues.get (gbs); 1662 1663 } 1664 1665 1670 public Object getSaveValue (Object id) 1671 { 1672 1673 if (this.parent != null) 1674 { 1675 1676 return this.parent.getSaveValue (id); 1677 1678 } 1679 1680 if ((this.qd == null) 1681 || 1682 (this.qd.saveValues == null) 1683 ) 1684 { 1685 1686 return null; 1687 1688 } 1689 1690 if (id instanceof String ) 1691 { 1692 1693 id = ((String ) id).toLowerCase (); 1694 1695 } 1696 1697 return this.qd.saveValues.get (id); 1698 1699 } 1700 1701 public String getQuery () 1702 { 1703 1704 return this.query; 1705 1706 } 1707 1708 1715 public void initOrderByComparator () 1716 throws QueryParseException 1717 { 1718 1719 if (this.orderBys != null) 1720 { 1721 1722 this.orderByComp = new ListExpressionComparator (this, 1724 false); 1725 1726 ListExpressionComparator lec = (ListExpressionComparator) this.orderByComp; 1727 1728 boolean allAccs = false; 1729 1730 int si = this.orderBys.size (); 1733 1734 for (int i = 0; i < si; i++) 1735 { 1736 1737 OrderBy ob = (OrderBy) this.orderBys.get (i); 1738 1739 Expression e = (Expression) ob.getExpression (); 1741 1742 if (e == null) 1743 { 1744 1745 int ci = ob.getIndex (); 1748 1749 if (ci == 0) 1750 { 1751 1752 throw new QueryParseException ("Order by column indices should start at 1."); 1753 1754 } 1755 1756 if (this.retObjs) 1757 { 1758 1759 throw new QueryParseException ("Cannot sort on a select column index when the objects are to be returned."); 1760 1761 } 1762 1763 if (ci > this.cols.size ()) 1764 { 1765 1766 throw new QueryParseException ("Invalid order by column index: " + 1767 ci + 1768 ", only: " + 1769 this.cols.size () + 1770 " columns are selected to be returned."); 1771 1772 } 1773 1774 SelectItemExpression sei = (SelectItemExpression) this.cols.get (ci - 1); 1776 1777 e = sei.getExpression (); 1779 1780 } else { 1781 1782 e.init (this); 1784 1785 } 1786 1787 if (!e.hasFixedResult (this)) 1790 { 1791 1792 lec.addSortItem (e, 1793 ob.getType ()); 1794 1795 } 1796 1797 } 1798 1799 } 1800 1801 } 1802 1803 1843 public QueryResults reorder (List objs, 1844 SortedMap dirs) 1845 throws QueryExecutionException, 1846 QueryParseException 1847 { 1848 1849 if (this.isWantObjects ()) 1850 { 1851 1852 throw new QueryParseException ("Only SQL statements that return columns (not the objects passed in) can be re-ordered."); 1853 1854 } 1855 1856 List obs = new ArrayList (); 1857 1858 Iterator iter = dirs.keySet ().iterator (); 1859 1860 while (iter.hasNext ()) 1861 { 1862 1863 Integer in = (Integer ) iter.next (); 1864 1865 if (in.intValue () > this.cols.size ()) 1867 { 1868 1869 throw new QueryParseException ("Cannot reorder: " + 1870 dirs.size () + 1871 " columns, only: " + 1872 this.cols.size () + 1873 " are present in the SQL statement."); 1874 1875 } 1876 1877 String dir = (String ) dirs.get (in); 1878 1879 int d = OrderBy.ASC; 1880 1881 if (dir.equals (Query.ORDER_BY_DESC)) 1882 { 1883 1884 d = OrderBy.DESC; 1885 1886 } 1887 1888 OrderBy ob = new OrderBy (); 1889 ob.setIndex (in.intValue ()); 1890 ob.setType (d); 1891 1892 obs.add (ob); 1893 1894 } 1895 1896 this.orderBys = obs; 1897 1898 this.initOrderByComparator (); 1899 1900 return this.execute (objs); 1902 1903 } 1904 1905 1936 public QueryResults reorder (List objs, 1937 String orderBys) 1938 throws QueryParseException, 1939 QueryExecutionException 1940 { 1941 1942 String sql = ""; 1943 1944 if (!orderBys.toLowerCase ().startsWith ("order by")) 1945 { 1946 1947 sql = sql + " ORDER BY "; 1948 1949 } 1950 1951 sql = sql + orderBys; 1952 1953 BufferedReader sr = new BufferedReader (new StringReader (sql)); 1954 1955 JoSQLParser parser = new JoSQLParser (sr); 1956 1957 List ors = null; 1958 1959 try 1960 { 1961 1962 ors = parser.OrderBys (); 1963 1964 } catch (Exception e) { 1965 1966 throw new QueryParseException ("Unable to parse order bys: " + 1967 orderBys, 1968 e); 1969 1970 } 1971 1972 this.orderBys = ors; 1973 1974 this.initOrderByComparator (); 1975 1976 return this.execute (objs); 1978 1979 } 1980 1981 public void setClassLoader (ClassLoader cl) 1982 { 1983 1984 this.classLoader = cl; 1985 1986 } 1987 1988 public ClassLoader getClassLoader () 1989 { 1990 1991 if (this.classLoader == null) 1992 { 1993 1994 this.classLoader = this.getClass ().getClassLoader (); 1997 1998 } 1999 2000 return this.classLoader; 2001 2002 } 2003 2004 public Class loadClass (String name) 2005 throws Exception 2006 { 2007 2008 return this.getClassLoader ().loadClass (name); 2009 2010 } 2011 2012 public void parse (String q) 2013 throws QueryParseException 2014 { 2015 2016 this.query = q; 2017 2018 BufferedReader sr = new BufferedReader (new StringReader (q)); 2019 2020 long s = System.currentTimeMillis (); 2021 2022 JoSQLParser parser = new JoSQLParser (sr); 2023 2024 this.addTiming ("Time to init josql parser object", 2025 System.currentTimeMillis () - s); 2026 2027 s = System.currentTimeMillis (); 2028 2029 try 2030 { 2031 2032 parser.parseQuery (this); 2033 2034 } catch (Exception e) { 2035 2036 throw new QueryParseException ("Unable to parse query: " + 2037 q, 2038 e); 2039 2040 } 2041 2042 this.isParsed = true; 2043 2044 this.addTiming ("Time to parse query into object form", 2045 System.currentTimeMillis () - s); 2046 2047 String className = null; 2048 2049 if (this.parent == null) 2051 { 2052 2053 if (!(this.from instanceof ConstantExpression)) 2054 { 2055 2056 throw new QueryParseException ("The FROM clause of the outer-most Query must be a string that denotes a fully-qualified class name, expression: " + 2057 this.from + 2058 " is not valid."); 2059 2060 } 2061 2062 String cn = null; 2064 2065 try 2066 { 2067 2068 cn = (String ) this.from.getValue (null, 2071 this); 2072 2073 } catch (Exception e) { 2074 2075 throw new QueryParseException ("Unable to determine FROM clause of the outer-most Query from expression: " + 2076 this.from + 2077 ", note: this exception shouldn't be able to happen, so something has gone SERIOUSLY wrong!", 2078 e); 2079 2080 } 2081 2082 if (!cn.equalsIgnoreCase ("null")) 2083 { 2084 2085 try 2087 { 2088 2089 this.objClass = this.loadClass (cn); 2090 2091 } catch (Exception e) { 2092 2093 throw new QueryParseException ("Unable to load FROM class: " + 2094 cn, 2095 e); 2096 2097 } 2098 2099 } 2100 2101 } 2102 2103 this.init (); 2105 2106 } 2107 2108 public void init () 2109 throws QueryParseException 2110 { 2111 2112 long s = System.currentTimeMillis (); 2113 2114 if (!this.retObjs) 2116 { 2117 2118 int aic = 0; 2119 2120 int si = this.cols.size (); 2121 2122 this.aliases = new HashMap (); 2123 2124 for (int i = 0; i < si; i++) 2125 { 2126 2127 SelectItemExpression exp = (SelectItemExpression) this.cols.get (i); 2128 2129 exp.init (this); 2130 2131 if (exp.isAddItemsFromCollectionOrMap ()) 2132 { 2133 2134 aic++; 2135 2136 } 2137 2138 String alias = exp.getAlias (); 2139 2140 if (alias != null) 2141 { 2142 2143 this.aliases.put (alias, 2144 new Integer (i + 1)); 2145 2146 } 2147 2148 this.aliases.put ((i + 1) + "", 2149 new Integer (i + 1)); 2150 2151 } 2152 2153 if ((aic > 0) 2154 && 2155 (aic != si) 2156 ) 2157 { 2158 2159 throw new QueryParseException ("If one or more SELECT clause columns is set to add the items returned from a: " + 2160 Map .class.getName () + 2161 " or: " + 2162 java.util.Collection .class.getName () + 2163 " then ALL columns must be marked to return the items as well."); 2164 2165 } 2166 2167 } 2168 2169 if (this.where != null) 2171 { 2172 2173 this.where.init (this); 2174 2175 } 2176 2177 if (this.having != null) 2179 { 2180 2181 this.having.init (this); 2182 2183 } 2184 2185 this.initOrderByComparator (); 2187 2188 if (this.groupBys != null) 2190 { 2191 2192 this.grouper = new Grouper (this); 2193 2194 int si = this.groupBys.size (); 2195 2196 for (int i = 0; i < si; i++) 2197 { 2198 2199 OrderBy ob = (OrderBy) this.groupBys.get (i); 2200 2201 Expression e = (Expression) ob.getExpression (); 2203 2204 if (e == null) 2205 { 2206 2207 int ci = ob.getIndex (); 2210 2211 if (ci == 0) 2212 { 2213 2214 throw new QueryParseException ("Order by column indices should start at 1."); 2215 2216 } 2217 2218 if (this.retObjs) 2219 { 2220 2221 throw new QueryParseException ("Cannot sort on a select column index when the objects are to be returned."); 2222 2223 } 2224 2225 if (ci > this.cols.size ()) 2226 { 2227 2228 throw new QueryParseException ("Invalid order by column index: " + 2229 ci + 2230 ", only: " + 2231 this.cols.size () + 2232 " columns are selected to be returned."); 2233 2234 } 2235 2236 SelectItemExpression sei = (SelectItemExpression) this.cols.get (ci - 1); 2238 2239 e = sei.getExpression (); 2241 2242 } else { 2243 2244 e.init (this); 2246 2247 } 2248 2249 this.grouper.addExpression (e); 2250 2251 } 2252 2253 } 2254 2255 if (this.groupOrderBys != null) 2256 { 2257 2258 if (this.grouper == null) 2259 { 2260 2261 throw new QueryParseException ("Group Order Bys are only valid if 1 or more Group By columns have been specified."); 2262 2263 } 2264 2265 Class c = this.objClass; 2268 2269 this.objClass = List .class; 2270 2271 this.groupOrderByComp = new GroupByExpressionComparator (this, 2273 false); 2274 2275 GroupByExpressionComparator lec = (GroupByExpressionComparator) this.groupOrderByComp; 2276 2277 List grouperExps = this.grouper.getExpressions (); 2278 2279 int si = this.groupOrderBys.size (); 2282 2283 for (int i = 0; i < si; i++) 2284 { 2285 2286 Integer k = new Integer (i); 2287 2288 OrderBy ob = (OrderBy) this.groupOrderBys.get (i); 2289 2290 if (ob.getIndex () > -1) 2291 { 2292 2293 int ci = ob.getIndex (); 2294 2295 if (ci == 0) 2296 { 2297 2298 throw new QueryParseException ("Group Order by column indices should start at 1."); 2299 2300 } 2301 2302 if (ci > grouperExps.size ()) 2303 { 2304 2305 throw new QueryParseException ("Invalid Group Order By column index: " + 2306 ci + 2307 ", only: " + 2308 grouperExps.size () + 2309 " Group By columns are selected to be returned."); 2310 2311 } 2312 2313 lec.addSortItem (null, 2314 ci - 1, 2317 ob.getType ()); 2318 2319 continue; 2320 2321 } 2322 2323 Expression e = (Expression) ob.getExpression (); 2325 2326 boolean cont = true; 2329 2330 for (int j = 0; j < grouperExps.size (); j++) 2331 { 2332 2333 Expression exp = (Expression) grouperExps.get (j); 2334 2335 if (e.equals (exp)) 2336 { 2337 2338 lec.addSortItem (null, 2340 j, 2341 ob.getType ()); 2342 2343 cont = false; 2344 2345 } 2346 2347 } 2348 2349 if (!cont) 2350 { 2351 2352 continue; 2353 2354 } 2355 2356 if ((e instanceof Function) 2357 || 2358 (e instanceof BindVariable) 2359 || 2360 (e instanceof SaveValue) 2361 ) 2362 { 2363 2364 e.init (this); 2365 2366 lec.addSortItem (e, 2367 -1, 2368 ob.getType ()); 2369 2370 continue; 2371 2372 } 2373 2374 throw new QueryParseException ("If the Group Order By: " + 2377 ob + 2378 " is not a function, a bind variable or a save value then it must be present in the Group By list."); 2379 2380 } 2381 2382 this.objClass = c; 2384 2385 } 2386 2387 if (this.groupByLimit != null) 2388 { 2389 2390 this.groupByLimit.init (this); 2391 2392 } 2393 2394 if (this.limit != null) 2395 { 2396 2397 this.limit.init (this); 2398 2399 } 2400 2401 if (this.executeOn != null) 2402 { 2403 2404 List allF = (List ) this.executeOn.get (Query.ALL); 2406 2407 if (allF != null) 2408 { 2409 2410 int si = allF.size (); 2412 2413 for (int i = 0; i < si; i++) 2414 { 2415 2416 AliasedExpression f = (AliasedExpression) allF.get (i); 2417 2418 f.init (this); 2419 2420 } 2421 2422 } 2423 2424 List resultsF = (List ) this.executeOn.get (Query.RESULTS); 2425 2426 if (resultsF != null) 2427 { 2428 2429 int si = resultsF.size (); 2431 2432 for (int i = 0; i < si; i++) 2433 { 2434 2435 AliasedExpression f = (AliasedExpression) resultsF.get (i); 2436 2437 f.init (this); 2438 2439 } 2440 2441 } 2442 2443 resultsF = (List ) this.executeOn.get (Query.GROUP_BY_RESULTS); 2444 2445 if (resultsF != null) 2446 { 2447 2448 int si = resultsF.size (); 2450 2451 for (int i = 0; i < si; i++) 2452 { 2453 2454 AliasedExpression f = (AliasedExpression) resultsF.get (i); 2455 2456 f.init (this); 2457 2458 } 2459 2460 } 2461 2462 } 2463 2464 this.addTiming ("Time to init Query objects", 2465 System.currentTimeMillis () - s); 2466 2467 } 2468 2469 2481 public void setFromObjectClass (Class c) 2482 { 2483 2484 this.objClass = c; 2485 2486 } 2487 2488 public Class getFromObjectClass () 2489 { 2490 2491 return this.objClass; 2492 2493 } 2494 2495 public void removeBindVariableChangedListener (BindVariableChangedListener bvl) 2496 { 2497 2498 List l = (List ) this.listeners.get ("bvs"); 2499 2500 if (l == null) 2501 { 2502 2503 return; 2504 2505 } 2506 2507 l.remove (bvl); 2508 2509 } 2510 2511 public void addBindVariableChangedListener (BindVariableChangedListener bvl) 2512 { 2513 2514 List l = (List ) this.listeners.get ("bvs"); 2515 2516 if (l == null) 2517 { 2518 2519 l = new ArrayList (); 2520 2521 this.listeners.put ("bvs", 2522 l); 2523 2524 } 2525 2526 if (!l.contains (bvl)) 2527 { 2528 2529 l.add (bvl); 2530 2531 } 2532 2533 } 2534 2535 public void removeSaveValueChangedListener (SaveValueChangedListener svl) 2536 { 2537 2538 List l = (List ) this.listeners.get ("svs"); 2539 2540 if (l == null) 2541 { 2542 2543 return; 2544 2545 } 2546 2547 l.remove (svl); 2548 2549 } 2550 2551 public void addSaveValueChangedListener (SaveValueChangedListener svl) 2552 { 2553 2554 List l = (List ) this.listeners.get ("svs"); 2555 2556 if (l == null) 2557 { 2558 2559 l = new ArrayList (); 2560 2561 this.listeners.put ("svs", 2562 l); 2563 2564 } 2565 2566 if (!l.contains (svl)) 2567 { 2568 2569 l.add (svl); 2570 2571 } 2572 2573 } 2574 2575 2615 2616 public Map getAliases () 2617 { 2618 2619 return this.aliases; 2620 2621 } 2622 2623 public boolean isWantObjects () 2624 { 2625 2626 return this.retObjs; 2627 2628 } 2629 2630 public void setWantObjects (boolean v) 2631 { 2632 2633 this.retObjs = v; 2634 2635 } 2636 2637 public char getWildcardCharacter () 2638 { 2639 2640 return this.wildcardChar; 2641 2642 } 2643 2644 public void setWildcardCharacter (char c) 2645 { 2646 2647 this.wildcardChar = c; 2648 2649 } 2650 2651 public void setLimit (Limit l) 2652 { 2653 2654 this.limit = l; 2655 2656 } 2657 2658 public Limit getLimit () 2659 { 2660 2661 return this.limit; 2662 2663 } 2664 2665 2671 public boolean parsed () 2672 { 2673 2674 return this.isParsed; 2675 2676 } 2677 2678 2683 public void setWantDistinctResults (boolean v) 2684 { 2685 2686 this.distinctResults = v; 2687 2688 } 2689 2690 public QueryResults getQueryResults () 2691 { 2692 2693 return this.qd; 2694 2695 } 2696 2697 2710 public List getOrderByColumns () 2711 { 2712 2713 return new ArrayList (this.orderBys); 2714 2715 } 2716 2717 public void setParent (Query q) 2718 { 2719 2720 this.parent = q; 2721 2722 } 2723 2724 public Query getParent () 2725 { 2726 2727 return this.parent; 2728 2729 } 2730 2731 public Query getTopLevelQuery () 2732 { 2733 2734 Query q = this; 2735 Query par = null; 2736 2737 while (true) 2738 { 2739 2740 par = q.getParent (); 2741 2742 if (par == null) 2743 { 2744 2745 break; 2746 2747 } 2748 2749 q = par; 2750 2751 } 2752 2753 return q; 2754 2755 } 2756 2757 public String toString () 2758 { 2759 2760 StringBuffer buf = new StringBuffer ("SELECT "); 2761 2762 if (this.distinctResults) 2763 { 2764 2765 buf.append ("DISTINCT "); 2766 2767 } 2768 2769 if (this.retObjs) 2770 { 2771 2772 buf.append ("*"); 2773 2774 } else { 2775 2776 for (int i = 0; i < this.cols.size (); i++) 2777 { 2778 2779 buf.append (" "); 2780 buf.append (this.cols.get (i)); 2781 2782 if (i < (this.cols.size () - 1)) 2783 { 2784 2785 buf.append (","); 2786 2787 } 2788 2789 } 2790 2791 } 2792 2793 buf.append (" FROM "); 2794 buf.append (this.from); 2795 2796 if (this.where != null) 2797 { 2798 2799 buf.append (" WHERE "); 2800 2801 buf.append (this.where); 2802 2803 } 2804 2805 return buf.toString (); 2806 2807 } 2808 2809} 2810 | Popular Tags |