📄 query.java
字号:
/* * Copyright 2004-2005 Gary Bentley * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.josql;import java.io.File;import java.io.StringReader;import java.io.BufferedReader;import java.util.Map;import java.util.HashMap;import java.util.SortedMap;import java.util.LinkedHashMap;import java.util.List;import java.util.ArrayList;import java.util.StringTokenizer;import java.util.Iterator;import java.util.Collections;import java.util.Arrays;import java.util.Comparator;import java.util.Set;import java.util.LinkedHashSet;import java.util.Collection;import org.josql.parser.JoSQLParser;import org.josql.expressions.*;import org.josql.functions.*;import org.josql.internal.*;import org.josql.events.*;/** * This class provides the ability for a developer to apply an arbitrary SQL statement * (using suitable syntax) to a collection of Java objects. * <p> * Basic usage: * <pre> * Query q = new Query (); * q.parse (myStatement); * List results = q.execute (myObjects); * </pre> * <p> * An example statement would look like: * <pre> * SELECT lastModified, * name * FROM java.io.File * WHERE name LIKE '%.html' * </pre> * <p> * The JoSQL functionality is large and complex, whilst basic queries like the one above are * perfectly possible, very complex queries are also possible, for example: * <pre> * SELECT name, * formatDate(lastModified), * formatNumber(length), * formatNumber(length - @avg_length), * formatTimeDuration(@max_last_modified - lastModified) * FROM java.io.File * WHERE lastModified > @avg_last_modified * AND length > @avg_length * AND lower(name) LIKE '%.html' * GROUP BY path * ORDER BY name, lastModified DESC * EXECUTE ON ALL avg (:_allobjs, length) avg_length, * avg (:_allobjs, lastModified) avg_last_modified, * max (:_allobjs, lastModified) max_last_modified * </pre> * <p> * Note: the "EXECUTE ON ALL" syntax is an extension used by JoSQL because it has no notion * of "aggregate functions". * <p> * For full details of how a query works and what is possible, see the * <a href="http://josql.sourceforge.net/manual/index.html">JoSQL User Manual</a>. * <p> * Please note that the package structure for JoSQL is deliberate, JoSQL is designed to be a * black box and lightweight thus only the <code>Query</code> object and associated exceptions * are exposed in the main package. Also, the class structure for JoSQL is not designed to * exactly represent the SQL statement passed to it, rather the classes are optimised for * ease of execution of the statement. If you wish to have a completely accurate Java object * view of ANY SQL statement then please see: * <a href="http://sourceforge.net/projects/jsqlparser">JSqlParser</a> * which will provide what you need. */public class Query{ public static String QUERY_BIND_VAR_NAME = "_query"; public static String PARENT_BIND_VAR_NAME = "_parent"; public static String CURR_OBJ_VAR_NAME = "_currobj"; public static String ALL_OBJS_VAR_NAME = "_allobjs"; public static String GRPBY_OBJ_VAR_NAME = "_grpby"; public static String GRPBY_OBJ_VAR_NAME_SYNONYM = "_groupby"; public static final String INT_BIND_VAR_PREFIX = "^^^"; public static final String ALL = "ALL"; public static final String RESULTS = "RESULTS"; public static final String GROUP_BY_RESULTS = "GROUP_BY_RESULTS"; public static final String WHERE_RESULTS = "WHERE_RESULTS"; public static final String HAVING_RESULTS = "HAVING_RESULTS"; public static final String ORDER_BY_ASC = "ASC"; public static final String ORDER_BY_DESC = "DESC"; public static final List nullQueryList = new ArrayList (); static { Query.nullQueryList.add (new Object ()); } private List bfhs = new ArrayList (); private Map bfhsMap = new HashMap (); private char wildcardChar = '%'; private Map aliases = new HashMap (); private List groupBys = null; private Comparator orderByComp = null; private Comparator groupOrderByComp = null; private Grouper grouper = null; private List orderBys = null; private List groupOrderBys = null; private List cols = null; private boolean retObjs = false; private Expression where = null; private Expression having = null; private Map bindVars = null; private String query = null; private boolean wantTimings = false; private List functionHandlers = null; private int anonVarIndex = 1; private Expression from = null; private Class objClass = null; private Limit limit = null; private Limit groupByLimit = null; private Map executeOn = null; private boolean isParsed = false; private boolean distinctResults = false; private ClassLoader classLoader = null; private Query parent = null; private Map listeners = new HashMap (); // Execution data. private transient Object currentObject = null; private transient List allObjects = null; private transient List currGroupBys = null; private QueryResults qd = null; /** * Return the WHERE clause expression. * * @return The WHERE clause as an expression. */ public Expression getWhereClause () { return this.where; } /** * Return the HAVING clause expression. * * @return The HAVING clause as an expression. */ public Expression getHavingClause () { return this.having; } /** * Return the {@link Comparator} we will use to do the ordering of the results, may be null. * * @return The Comparator. */ public Comparator getOrderByComparator () { return this.orderByComp; } public FunctionHandler getFunctionHandler (String id) { if (this.parent != null) { return this.parent.getFunctionHandler (id); } return (FunctionHandler) this.bfhsMap.get (id); } private void initFunctionHandlers () { FunctionHandler o = new CollectionFunctions (); o.setQuery (this); this.bfhsMap.put (CollectionFunctions.HANDLER_ID, o); this.bfhs.add (o); o = new StringFunctions (); o.setQuery (this); this.bfhsMap.put (StringFunctions.HANDLER_ID, o); this.bfhs.add (o); o = new ConversionFunctions (); o.setQuery (this); this.bfhsMap.put (ConversionFunctions.HANDLER_ID, o); this.bfhs.add (o); o = new FormattingFunctions (); o.setQuery (this); this.bfhsMap.put (FormattingFunctions.HANDLER_ID, o); this.bfhs.add (o); o = new GroupingFunctions (); o.setQuery (this); this.bfhsMap.put (GroupingFunctions.HANDLER_ID, o); this.bfhs.add (o); o = new MiscellaneousFunctions (); o.setQuery (this); this.bfhsMap.put (MiscellaneousFunctions.HANDLER_ID, o); this.bfhs.add (o); } public Map getExecuteOnFunctions () { return this.executeOn; } public void setExecuteOnFunctions (Map ex) { this.executeOn = ex; } public String getAnonymousBindVariableName () { if (this.parent != null) { return this.parent.getAnonymousBindVariableName (); } String n = Query.INT_BIND_VAR_PREFIX + this.anonVarIndex; this.anonVarIndex++; return n; } public List getDefaultFunctionHandlers () { if (this.parent != null) { return this.parent.getDefaultFunctionHandlers (); } return new ArrayList (this.bfhs); } public List getFunctionHandlers () { if (this.parent != null) { return this.parent.getFunctionHandlers (); } return this.functionHandlers; } public void addFunctionHandler (Object o) { if (this.parent != null) { this.parent.addFunctionHandler (o); } if (this.functionHandlers == null) { this.functionHandlers = new ArrayList (); } if (o instanceof FunctionHandler) { FunctionHandler fh = (FunctionHandler) o; fh.setQuery (this); } this.functionHandlers.add (o); } public void setFrom (Expression exp) { this.from = exp; } public Expression getFrom () { return this.from; } public void setClassName (String n) { ConstantExpression ce = new ConstantExpression (); this.from = ce; ce.setValue (n); } public void setOrderByColumns (List cols) { this.orderBys = cols; } public void setGroupByLimit (Limit g) { this.groupByLimit = g; } public void setGroupByOrderColumns (List cols) { this.groupOrderBys = cols; } public List getGroupByColumns () { return this.groupBys; } public void setGroupByColumns (List cols) { this.groupBys = cols; } public List getColumns () { return this.cols; } public void setColumns (List cols) { this.cols = cols; } public void setHaving (Expression be) { this.having = be; } public void setWhere (Expression be) { this.where = be; } public Query () { this.initFunctionHandlers (); } public void setWantTimings (boolean v) { this.wantTimings = v; } protected void addTiming (String id, double time) { if (this.wantTimings) { if (this.qd == null) { return; } if (this.qd.timings == null) { this.qd.timings = new LinkedHashMap (); } this.qd.timings.put (id, new Double (time)); } } public Object getVariable (int index) { if (this.parent != null) { return this.parent.getVariable (index); } return this.getVariable (Query.INT_BIND_VAR_PREFIX + index); } public Class getVariableClass (String name) { String n = name.toLowerCase (); if (n.equals (Query.QUERY_BIND_VAR_NAME)) { // Return the query itself! return Query.class; } if (n.equals (Query.PARENT_BIND_VAR_NAME)) { // Return the query itself! return Query.class; } if (n.equals (Query.CURR_OBJ_VAR_NAME)) { // May be null if we aren't processing a while/having expression. return this.objClass; } if (n.equals (Query.ALL_OBJS_VAR_NAME)) { // May change depending upon when it is called. return List.class; } if (this.parent != null) { return this.parent.getVariableClass (n); } if (this.bindVars == null) { return Object.class; } Object v = (Object) this.bindVars.get (n); if (v == null) { return Object.class; } return v.getClass (); } public Object getGroupByVariable (int ind) { // Get the current group bys. if (this.currGroupBys != null) { return this.currGroupBys.get (ind - 1); } return null; } public Object getVariable (String name) { String n = name.toLowerCase (); if (n.equals (Query.QUERY_BIND_VAR_NAME)) { // Return the query itself! return this; } if (n.equals (Query.PARENT_BIND_VAR_NAME)) { // Return the parent query. return this.parent; } if (n.equals (Query.CURR_OBJ_VAR_NAME)) { // May be null if we aren't processing a while/having expression. return this.currentObject; } if (n.equals (Query.ALL_OBJS_VAR_NAME)) { // May change depending upon when it is called. return this.allObjects; } if (this.parent != null) { return this.parent.getVariable (name); } if (this.bindVars == null) { return null; } return this.bindVars.get (n); } public void setVariable (String name, Object v) { if (this.parent != null) { this.parent.setVariable (name, v); return; } if (this.bindVars == null) { this.bindVars = new HashMap (); } this.bindVars.put (name.toLowerCase (), v); } public void setVariable (int index, Object v) { if (this.parent != null) { this.parent.setVariable (index, v); return; } this.setVariable (Query.INT_BIND_VAR_PREFIX + index, v); } public Map getVariables () { if (this.parent != null) { return this.parent.getVariables (); } return this.bindVars; } public boolean isWhereTrue (Object o) throws QueryExecutionException { if (this.where == null) { // A null where means yes!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -