📄 query.java
字号:
return true; } return this.where.isTrue (o, this); } public void setVariables (Map bVars) { if (this.parent != null) { this.parent.setVariables (bVars); return; } this.bindVars = bVars; } /** * Execute all the expressions for the specified type, either: {@link #ALL} or: * {@link #RESULTS}. If the expressions are aliased then the results will be * available in the save results upon completion. * * @param l The List of objects to execute the functions on. * @param t The type of expressions to execute. * @throws QueryExecutionException If there is an issue with executing one of the * expressions or if the Query hasn't been inited yet. */ public void doExecuteOn (List l, String t) throws QueryExecutionException { if (!this.isParsed) { throw new QueryExecutionException ("Query has not been initialised."); } if (this.executeOn != null) { // Set the "all objects". this.allObjects = l; long s = System.currentTimeMillis (); List fs = (List) this.executeOn.get (t); if (fs != null) { // Execute each one in turn. int si = fs.size (); for (int i = 0; i < si; i++) { AliasedExpression f = (AliasedExpression) fs.get (i); Object o = f.getValue (null, this); String af = f.getAlias (); if (af != null) { this.setSaveValue (af, o); } } this.addTiming ("Total time to execute: " + si + " expression(s) on " + t + " objects", System.currentTimeMillis () - s); } } } /** * Clear all the results, it is important to call this method when you have completed * execution of the Query if you are planning to re-use the Query (i.e. that it will * NOT fall out of scope and be automatically cleaned up by the GC). * If you don't call this method then references to your objects will be kept and * prevent transient objects from being "cleaned" up by the GC until the next time * that this Query is executed. You have been warned! */ public void clearResults () { this.qd = null; this.currentObject = null; this.allObjects = null; } /** * Execute this query on the specified objects. * * @param objs The list of objects to execute the query on. * @return The list of objects that match the query. * @throws QueryExecutionException If the query cannot be executed. */ public QueryResults execute (List objs) throws QueryExecutionException { if ((objs == null) && (this.objClass != null) ) { throw new QueryExecutionException ("List of objects must be non-null when an object class is specified."); } this.qd = new QueryResults (); if ((this.objClass == null) && (objs == null) ) { objs = Query.nullQueryList; } this.allObjects = objs; long s = System.currentTimeMillis (); // See if we have any expressions that are to be executed on // the complete set. if (this.executeOn != null) { this.doExecuteOn (objs, Query.ALL); } s = System.currentTimeMillis (); if (this.where != null) { int si = objs.size (); // Create the where results with "about" half the size of the input collection. // Further optimizations may be possible here if some statistics are collected // about how many objects match/fail the where clause and then increase the // capacity of the where results list as required, i.e. to cut down on the number // of array copy and allocation operations performed. For now though half will do ;) this.qd.whereResults = new ArrayList (si / 2); for (int i = 0; i < si; i++) { Object o = objs.get (i); this.currentObject = o; boolean res = this.where.isTrue (o, this); if (res) { this.qd.whereResults.add (o); } } } else { // No limiting where clause so what's passed in is what comes out. this.qd.whereResults = objs; } double wet = (double) System.currentTimeMillis () - (double) s; this.addTiming ("Total time to execute Where clause on all objects", wet); this.addTiming ("Where took average over: " + objs.size () + " objects", wet / (double) objs.size ()); this.allObjects = this.qd.whereResults; // The results here are the result of executing the where clause, if present. this.qd.results = this.qd.whereResults; // See if we have any functions that are to be executed on // the results... if (this.executeOn != null) { this.doExecuteOn (this.qd.results, Query.RESULTS); } // If we have a "having" clause execute it here... if (this.having != null) { int si = this.qd.results.size (); this.qd.havingResults = new ArrayList (si); for (int i = 0; i < si; i++) { Object o = this.qd.results.get (i); this.currentObject = o; if (this.having.isTrue (o, this)) { this.qd.havingResults.add (o); } } this.qd.results = this.qd.havingResults; // Future proofing... this.allObjects = this.qd.results; } // Now perform the group by operation. if (this.grouper != null) { // Need to handle the fact that this will return a Map of Lists... try { s = System.currentTimeMillis (); Map mres = this.grouper.group (this.qd.results); this.qd.groupByResults = mres; List grpBys = new ArrayList (mres.keySet ()); // Now order the group bys, if present. if (this.groupOrderByComp != null) { Map origSvs = this.qd.saveValues; Collections.sort (grpBys, this.groupOrderByComp); // "Restore" the save values. this.qd.saveValues = origSvs; GroupByExpressionComparator lec = (GroupByExpressionComparator) this.groupOrderByComp; if (lec.getException () != null) { 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.", lec.getException ()); } lec.clearCache (); } // Now limit the group bys, if required. if (this.groupByLimit != null) { s = System.currentTimeMillis (); grpBys = this.groupByLimit.getSubList (grpBys, this); this.addTiming ("Total time to limit group by results size", System.currentTimeMillis () - s); } long t = System.currentTimeMillis (); this.addTiming ("Group operation took", (double) (t - s)); s = System.currentTimeMillis (); // Convert the keys in the group by to a List. if ((this.orderByComp != null) || (!this.retObjs) ) { Map origSvs = this.qd.saveValues; Map nres = new LinkedHashMap (); int gs = grpBys.size (); for (int i = 0; i < gs; i++) { List l = (List) grpBys.get (i); List lr = (List) mres.get (l); this.allObjects = lr; this.currGroupBys = l; // Now set the save values for the group bys. if (this.qd.groupBySaveValues == null) { this.qd.groupBySaveValues = new HashMap (); } this.qd.saveValues = new HashMap (); this.qd.groupBySaveValues.put (l, this.qd.saveValues); // Now execute all (any) group by results functions. this.doExecuteOn (lr, Query.GROUP_BY_RESULTS); // Now sort these according to the order by (if any). if ((lr.size () > 1) && (this.orderByComp != null) ) { Collections.sort (lr, this.orderByComp); ListExpressionComparator lec = (ListExpressionComparator) this.orderByComp; if (lec.getException () != null) { throw new QueryExecutionException ("Unable to order group by results", lec.getException ()); } lec.clearCache (); } if (!this.retObjs) { // Now collect the values... Collection res = null; if (!this.distinctResults) { res = new ArrayList (); } else { res = new LinkedHashSet (); } this.getColumnValues (lr, res); if (this.distinctResults) { lr = new ArrayList (res); } else { lr = (List) res; } } else { if (this.distinctResults) { this.qd.results = ((CollectionFunctions) this.getFunctionHandler (CollectionFunctions.HANDLER_ID)).unique (this.qd.results); } } if (this.limit != null) { lr = this.limit.getSubList (lr, this); } nres.put (l, lr); } this.qd.groupByResults = nres; // "Restore" the save values. this.qd.saveValues = origSvs; } t = System.currentTimeMillis (); this.addTiming ("Group column collection and sort took", (double) (t - s)); this.qd.results = grpBys; return this.qd; } catch (Exception e) { throw new QueryExecutionException ("Unable to perform group by operation", e); } } // Now perform the order by. if ((this.qd.results.size () > 1) && (this.orderByComp != null) ) { s = System.currentTimeMillis (); // It should be noted here that the comparator will set the // "current object" so that it can be used in the order by // clause. Collections.sort (this.qd.results, this.orderByComp); this.addTiming ("Total time to order results", System.currentTimeMillis () - s); } if (this.orderByComp != null) { ListExpressionComparator lec = (ListExpressionComparator) this.orderByComp; if (lec.getException () != null) { throw new QueryExecutionException ("Unable to order results", lec.getException ()); } lec.clearCache (); } // Finally, if we have a limit clause, restrict the set of objects returned... if (this.limit != null) { s = System.currentTimeMillis (); this.qd.results = this.limit.getSubList (this.qd.results, this); this.addTiming ("Total time to limit results size", System.currentTimeMillis () - s); } boolean retNewObjs = false; // See if we are a single column of new objects. if (!this.retObjs) { if (this.cols.size () == 1) { SelectItemExpression sei = (SelectItemExpression) this.cols.get (0); if (sei.getExpression () instanceof NewObjectExpression) { retNewObjs = true; } } } // Now get the columns if necessary, we do this here to get the minimum // set of objects required. if ((!this.retObjs) && (!retNewObjs) ) { s = System.currentTimeMillis (); Collection resC = null; if (!this.distinctResults) { resC = new ArrayList (this.qd.results.size ()); } else { resC = new LinkedHashSet (this.qd.results.size ()); } // Get the column values. this.getColumnValues (this.qd.results, resC); if (this.distinctResults) { this.qd.results = new ArrayList (resC); } else { this.qd.results = (List) resC; } this.addTiming ("Collection of results took", (double) (System.currentTimeMillis () - s)); } else { if (this.retObjs) { if (this.distinctResults) { s = System.currentTimeMillis (); this.qd.results = ((CollectionFunctions) this.getFunctionHandler (CollectionFunctions.HANDLER_ID)).unique (this.qd.results); this.addTiming ("Collecting unique results took", (double) (System.currentTimeMillis () - s)); } } // If we want a single column of new objects... if (retNewObjs) { this.qd.results = this.getNewObjectSingleColumnValues (this.qd.results); } } try { return this.qd; } finally { // Clean up ;) this.clearResults (); } } public void setCurrentGroupByObjects (List objs) { this.currGroupBys = objs; } public List getAllObjects () { return this.allObjects; } public void setAllObjects (List objs) { this.allObjects = objs; } public void setCurrentObject (Object o) { this.currentObject = o; } public Object getCurrentObject () { return this.currentObject; } private void getColumnValues (List res, Collection rs) throws QueryExecutionException { int s = res.size (); int cs = this.cols.size (); boolean addItems = false; for (int i = 0; i < s; i++) { Object o = res.get (i); this.currentObject = o; List sRes = new ArrayList (cs); for (int j = 0; j < cs; j++) { SelectItemExpression v = (SelectItemExpression) this.cols.get (j); try { if (v.isAddItemsFromCollectionOrMap ()) { addItems = true; } // Get the value from the object... Object ov = v.getValue (o, this); if (addItems) { rs.addAll (v.getAddItems (ov)); } else { sRes.add (ov); } // Now since the expression can set the current object, put it // back to rights after the call...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -