📄 whereparser.java
字号:
//$Id: WhereParser.java,v 1.17.2.15 2003/12/13 11:32:41 oneovthafew Exp $package net.sf.hibernate.hql;import java.util.HashMap;import java.util.HashSet;import java.util.LinkedList;import java.util.Map;import java.util.Set;import java.util.StringTokenizer;import net.sf.hibernate.MappingException;import net.sf.hibernate.QueryException;import net.sf.hibernate.util.ReflectHelper;import net.sf.hibernate.util.StringHelper;import net.sf.hibernate.persister.Queryable;import net.sf.hibernate.sql.InFragment;import net.sf.hibernate.sql.JoinFragment;import net.sf.hibernate.type.EntityType;import net.sf.hibernate.type.LiteralType;import net.sf.hibernate.type.Type;import net.sf.hibernate.type.TypeFactory;/** * Parses the where clause of a hibernate query and translates it to an * SQL where clause. */// We should reengineer this class so that, rather than the current ad -// hoc linear approach to processing a stream of tokens, we instead// build up a tree of expressions.// We would probably refactor to have LogicParser (builds a tree of simple// expressions connected by and, or, not), ExpressionParser (translates// from OO terms like foo, foo.Bar, foo.Bar.Baz to SQL terms like// FOOS.ID, FOOS.BAR_ID, etc) and PathExpressionParser (which does much// the same thing it does now)public class WhereParser implements Parser { private final PathExpressionParser pathExpressionParser; { pathExpressionParser = new PathExpressionParser(); pathExpressionParser.setUseThetaStyleJoin(true); //Need this, since join condition can appear inside parens! } private static final Set EXPRESSION_TERMINATORS = new HashSet(); //tokens that close a sub expression private static final Set EXPRESSION_OPENERS = new HashSet(); //tokens that open a sub expression private static final Set BOOLEAN_OPERATORS = new HashSet(); //tokens that would indicate a sub expression is a boolean expression private static final Map NEGATIONS = new HashMap(); static { EXPRESSION_TERMINATORS.add("and"); EXPRESSION_TERMINATORS.add("or"); EXPRESSION_TERMINATORS.add(StringHelper.CLOSE_PAREN); //expressionTerminators.add(","); // deliberately excluded EXPRESSION_OPENERS.add("and"); EXPRESSION_OPENERS.add("or"); EXPRESSION_OPENERS.add(StringHelper.OPEN_PAREN); //expressionOpeners.add(","); // deliberately excluded BOOLEAN_OPERATORS.add("<"); BOOLEAN_OPERATORS.add("="); BOOLEAN_OPERATORS.add(">"); BOOLEAN_OPERATORS.add("#"); BOOLEAN_OPERATORS.add("~"); BOOLEAN_OPERATORS.add("like"); BOOLEAN_OPERATORS.add("ilike"); BOOLEAN_OPERATORS.add("is"); BOOLEAN_OPERATORS.add("in"); BOOLEAN_OPERATORS.add("any"); BOOLEAN_OPERATORS.add("some"); BOOLEAN_OPERATORS.add("all"); BOOLEAN_OPERATORS.add("exists"); BOOLEAN_OPERATORS.add("between"); BOOLEAN_OPERATORS.add("<="); BOOLEAN_OPERATORS.add(">="); BOOLEAN_OPERATORS.add("=>"); BOOLEAN_OPERATORS.add("=<"); BOOLEAN_OPERATORS.add("!="); BOOLEAN_OPERATORS.add("<>"); BOOLEAN_OPERATORS.add("!#"); BOOLEAN_OPERATORS.add("!~"); BOOLEAN_OPERATORS.add("!<"); BOOLEAN_OPERATORS.add("!>"); BOOLEAN_OPERATORS.add("is not"); BOOLEAN_OPERATORS.add("not like"); BOOLEAN_OPERATORS.add("not ilike"); BOOLEAN_OPERATORS.add("not in"); BOOLEAN_OPERATORS.add("not between"); BOOLEAN_OPERATORS.add("not exists"); NEGATIONS.put("and", "or"); NEGATIONS.put("or", "and"); NEGATIONS.put("<", ">="); NEGATIONS.put("=", "<>"); NEGATIONS.put(">", "<="); NEGATIONS.put("#", "!#"); NEGATIONS.put("~", "!~"); NEGATIONS.put("like", "not like"); NEGATIONS.put("ilike", "not ilike"); NEGATIONS.put("is", "is not"); NEGATIONS.put("in", "not in"); NEGATIONS.put("exists", "not exists"); NEGATIONS.put("between", "not between"); NEGATIONS.put("<=", ">"); NEGATIONS.put(">=", "<"); NEGATIONS.put("=>", "<"); NEGATIONS.put("=<", ">"); NEGATIONS.put("!=", "="); NEGATIONS.put("<>", "="); NEGATIONS.put("!#", "#"); NEGATIONS.put("!~", "~"); NEGATIONS.put("!<", ">="); NEGATIONS.put("!>", "<="); NEGATIONS.put("is not", "is"); NEGATIONS.put("not like", "like"); NEGATIONS.put("not ilike", "ilike"); NEGATIONS.put("not in", "in"); NEGATIONS.put("not between", "between"); NEGATIONS.put("not exists", "exists"); } // Handles things like: // a and b or c // a and ( b or c ) // not a and not b // not ( a and b ) // x between y and z (overloaded "and") // x in ( a, b, c ) (overloaded brackets) // not not a // a is not null (overloaded "not") // etc...... // and expressions like // foo = bar (maps to: foo.id = bar.id) // foo.Bar = 'foo' (maps to: foo.bar = 'foo') // foo.Bar.Baz = 1.0 (maps to: foo.bar = bar.id and bar.baz = 1.0) // 1.0 = foo.Bar.Baz (maps to: bar.baz = 1.0 and foo.Bar = bar.id) // foo.Bar.Baz = a.B.C (maps to: bar.Baz = b.C and foo.Bar = bar.id and a.B = b.id) // foo.Bar.Baz + a.B.C (maps to: bar.Baz + b.C and foo.Bar = bar.id and a.B = b.id) // ( foo.Bar.Baz + 1.0 ) < 2.0 (maps to: ( bar.Baz + 1.0 ) < 2.0 and foo.Bar = bar.id) private boolean betweenSpecialCase = false; //Inside a BETWEEN ... AND ... expression private boolean negated = false; private boolean inSubselect = false; private int bracketsSinceSelect = 0; private StringBuffer subselect; private boolean expectingPathContinuation = false; private int expectingIndex = 0; // The following variables are stacks that keep information about each subexpression // in the list of nested subexpressions we are currently processing. private LinkedList nots = new LinkedList(); //were an odd or even number of NOTs encountered private LinkedList joins = new LinkedList(); //the join string built up by compound paths inside this expression private LinkedList booleanTests = new LinkedList(); //a flag indicating if the subexpression is known to be boolean private String getElementName(PathExpressionParser.CollectionElement element, QueryTranslator q) throws QueryException { String name; if ( element.isOneToMany ) { name = element.alias; } else { Type type = element.elementType; Class clazz; if ( type.isEntityType() ) { //ie. a many-to-many clazz = ( (EntityType) type ).getAssociatedClass(); name = pathExpressionParser.continueFromManyToMany(clazz, element.elementColumns, q); } else { throw new QueryException("illegally dereferenced collection element"); } } return name; } public void token(String token, QueryTranslator q) throws QueryException { String lcToken = token.toLowerCase(); //Cope with [,] if ( token.equals("[") && !expectingPathContinuation ) { expectingPathContinuation = false; if (expectingIndex==0) throw new QueryException("unexpected ["); return; } else if ( token.equals("]") ) { expectingIndex--; expectingPathContinuation = true; return; } //Cope with a continued path expression (ie. ].baz) if (expectingPathContinuation) { boolean pathExpressionContinuesFurther = continuePathExpression(token, q); if (pathExpressionContinuesFurther) return; //NOTE: early return } //Cope with a subselect if ( !inSubselect && ( lcToken.equals("select") || lcToken.equals("from") ) ) { inSubselect=true; subselect = new StringBuffer(20); } if ( inSubselect && token.equals(StringHelper.CLOSE_PAREN) ) { bracketsSinceSelect--; if (bracketsSinceSelect==-1) { QueryTranslator subq = new QueryTranslator( subselect.toString() ); try { subq.compile(q); } catch (MappingException me) { throw new QueryException("MappingException occurred compiling subquery", me ); } appendToken( q, subq.getSQLString() ); inSubselect = false; bracketsSinceSelect=0; } } if (inSubselect) { if ( token.equals(StringHelper.OPEN_PAREN) ) bracketsSinceSelect++; subselect.append(token).append(' '); return; } //Cope with special cases of AND, NOT, () specialCasesBefore(lcToken); //Close extra brackets we opened if ( !betweenSpecialCase && EXPRESSION_TERMINATORS.contains(lcToken) ) { closeExpression(q, lcToken); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -