WhereParserpublic class WhereParser extends Object implements ParserParses the where clause of a hibernate query and translates it to an
SQL where clause. |
Fields Summary |
---|
private final PathExpressionParser | pathExpressionParser | private static final Set | EXPRESSION_TERMINATORS | private static final Set | EXPRESSION_OPENERS | private static final Set | BOOLEAN_OPERATORS | private static final Map | NEGATIONS | private boolean | betweenSpecialCase | private boolean | negated | private boolean | inSubselect | private int | bracketsSinceSelect | private StringBuffer | subselect | private boolean | expectingPathContinuation | private int | expectingIndex | private LinkedList | nots | private LinkedList | joins | private LinkedList | booleanTests |
Methods Summary |
---|
private void | addJoin(org.hibernate.engine.JoinSequence joinSequence, QueryTranslatorImpl q)
//JoinFragment fromClause = q.createJoinFragment(true);
//fromClause.addJoins( join.toJoinFragment().toFromFragmentString(), StringHelper.EMPTY_STRING );
q.addFromJoinOnly( pathExpressionParser.getName(), joinSequence );
try {
addToCurrentJoin( joinSequence.toJoinFragment( q.getEnabledFilters(), true ).toWhereFragmentString() );
}
catch ( MappingException me ) {
throw new QueryException( me );
}
| private void | addToCurrentJoin(java.lang.String sql)
( ( StringBuffer ) joins.getLast() ).append( sql );
| private void | addToCurrentJoin(PathExpressionParser.CollectionElement ce)
try {
addToCurrentJoin( ce.joinSequence.toJoinFragment().toWhereFragmentString() + ce.indexValue.toString() );
}
catch ( MappingException me ) {
throw new QueryException( me );
}
| void | appendToken(QueryTranslatorImpl q, java.lang.String token)
if ( expectingIndex > 0 ) {
pathExpressionParser.setLastCollectionElementIndexValue( token );
}
else {
q.appendWhereToken( token );
}
| private void | closeExpression(QueryTranslatorImpl q, java.lang.String lcToken)
if ( ( ( Boolean ) booleanTests.removeLast() ).booleanValue() ) { //it was a boolean expression
if ( booleanTests.size() > 0 ) {
// the next one up must also be
booleanTests.removeLast();
booleanTests.addLast( Boolean.TRUE );
}
// Add any joins
appendToken( q, ( joins.removeLast() ).toString() );
}
else {
StringBuffer join = ( StringBuffer ) joins.removeLast();
( ( StringBuffer ) joins.getLast() ).append( join.toString() );
}
if ( ( ( Boolean ) nots.removeLast() ).booleanValue() ) negated = !negated;
if ( !")".equals( lcToken ) ) appendToken( q, ")" );
| private boolean | continuePathExpression(java.lang.String token, QueryTranslatorImpl q)
expectingPathContinuation = false;
PathExpressionParser.CollectionElement element = pathExpressionParser.lastCollectionElement();
if ( token.startsWith( "." ) ) { // the path expression continues after a ]
doPathExpression( getElementName( element, q ) + token, q ); // careful with this!
addToCurrentJoin( element );
return true; //NOTE: EARLY EXIT!
}
else { // the path expression ends at the ]
if ( element.elementColumns.length != 1 ) {
throw new QueryException( "path expression ended in composite collection element" );
}
appendToken( q, element.elementColumns[0] );
addToCurrentJoin( element );
return false;
}
| private void | doPathExpression(java.lang.String token, QueryTranslatorImpl q)
preprocess( token, q );
StringTokenizer tokens = new StringTokenizer( token, ".", true );
pathExpressionParser.start( q );
while ( tokens.hasMoreTokens() ) {
pathExpressionParser.token( tokens.nextToken(), q );
}
pathExpressionParser.end( q );
if ( pathExpressionParser.isCollectionValued() ) {
openExpression( q, "" );
appendToken( q, pathExpressionParser.getCollectionSubquery( q.getEnabledFilters() ) );
closeExpression( q, "" );
// this is ugly here, but needed because its a subquery
q.addQuerySpaces( q.getCollectionPersister( pathExpressionParser.getCollectionRole() ).getCollectionSpaces() );
}
else {
if ( pathExpressionParser.isExpectingCollectionIndex() ) {
expectingIndex++;
}
else {
addJoin( pathExpressionParser.getWhereJoin(), q );
appendToken( q, pathExpressionParser.getWhereColumn() );
}
}
| private void | doToken(java.lang.String token, QueryTranslatorImpl q)
if ( q.isName( StringHelper.root( token ) ) ) { //path expression
doPathExpression( q.unalias( token ), q );
}
else if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) { //named query parameter
q.addNamedParameter( token.substring( 1 ) );
appendToken( q, "?" );
}
else {
Queryable persister = q.getEntityPersisterUsingImports( token );
if ( persister != null ) { // the name of a class
final String discrim = persister.getDiscriminatorSQLValue();
if ( InFragment.NULL.equals(discrim) || InFragment.NOT_NULL.equals(discrim) ) {
throw new QueryException( "subclass test not allowed for null or not null discriminator" );
}
else {
appendToken( q, discrim );
}
}
else {
Object constant;
if (
token.indexOf( '." ) > -1 &&
( constant = ReflectHelper.getConstantValue( token ) ) != null
) {
Type type;
try {
type = TypeFactory.heuristicType( constant.getClass().getName() );
}
catch ( MappingException me ) {
throw new QueryException( me );
}
if ( type == null ) throw new QueryException( QueryTranslator.ERROR_CANNOT_DETERMINE_TYPE + token );
try {
appendToken( q, ( ( LiteralType ) type ).objectToSQLString( constant, q.getFactory().getDialect() ) );
}
catch ( Exception e ) {
throw new QueryException( QueryTranslator.ERROR_CANNOT_FORMAT_LITERAL + token, e );
}
}
else { //anything else
String negatedToken = negated ? ( String ) NEGATIONS.get( token.toLowerCase() ) : null;
if ( negatedToken != null && ( !betweenSpecialCase || !"or".equals( negatedToken ) ) ) {
appendToken( q, negatedToken );
}
else {
appendToken( q, token );
}
}
}
}
| public void | end(QueryTranslatorImpl q)
if ( expectingPathContinuation ) {
expectingPathContinuation = false;
PathExpressionParser.CollectionElement element = pathExpressionParser.lastCollectionElement();
if ( element.elementColumns.length != 1 ) throw new QueryException( "path expression ended in composite collection element" );
appendToken( q, element.elementColumns[0] );
addToCurrentJoin( element );
}
token( ")", q );
| private java.lang.String | getElementName(PathExpressionParser.CollectionElement element, QueryTranslatorImpl q) //a flag indicating if the subexpression is known to be boolean
String name;
if ( element.isOneToMany ) {
name = element.alias;
}
else {
Type type = element.elementType;
if ( type.isEntityType() ) { //ie. a many-to-many
String entityName = ( ( EntityType ) type ).getAssociatedEntityName();
name = pathExpressionParser.continueFromManyToMany( entityName, element.elementColumns, q );
}
else {
throw new QueryException( "illegally dereferenced collection element" );
}
}
return name;
| private void | openExpression(QueryTranslatorImpl q, java.lang.String lcToken)
nots.addLast( Boolean.FALSE );
booleanTests.addLast( Boolean.FALSE );
joins.addLast( new StringBuffer() );
if ( !"(".equals( lcToken ) ) appendToken( q, "(" );
| private void | preprocess(java.lang.String token, QueryTranslatorImpl q)
// ugly hack for cases like "elements(foo.bar.collection)"
// (multi-part path expression ending in elements or indices)
String[] tokens = StringHelper.split( ".", token, true );
if (
tokens.length > 5 &&
( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( tokens[tokens.length - 1] )
|| CollectionPropertyNames.COLLECTION_INDICES.equals( tokens[tokens.length - 1] ) )
) {
pathExpressionParser.start( q );
for ( int i = 0; i < tokens.length - 3; i++ ) {
pathExpressionParser.token( tokens[i], q );
}
pathExpressionParser.token( null, q );
pathExpressionParser.end( q );
addJoin( pathExpressionParser.getWhereJoin(), q );
pathExpressionParser.ignoreInitialJoin();
}
| private void | specialCasesAfter(java.lang.String lcToken)
if ( betweenSpecialCase && lcToken.equals( "and" ) ) {
betweenSpecialCase = false;
}
| private void | specialCasesBefore(java.lang.String lcToken)
if ( lcToken.equals( "between" ) || lcToken.equals( "not between" ) ) {
betweenSpecialCase = true;
}
| public void | start(QueryTranslatorImpl q)
token( "(", q );
| public void | token(java.lang.String token, QueryTranslatorImpl q)
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( ")" ) ) {
bracketsSinceSelect--;
if ( bracketsSinceSelect == -1 ) {
QueryTranslatorImpl subq = new QueryTranslatorImpl(
subselect.toString(),
q.getEnabledFilters(),
q.getFactory()
);
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( "(" ) ) 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 );
}
//take note when this is a boolean expression
if ( BOOLEAN_OPERATORS.contains( lcToken ) ) {
booleanTests.removeLast();
booleanTests.addLast( Boolean.TRUE );
}
if ( lcToken.equals( "not" ) ) {
nots.addLast( new Boolean( !( ( Boolean ) nots.removeLast() ).booleanValue() ) );
negated = !negated;
return; //NOTE: early return
}
//process a token, mapping OO path expressions to SQL expressions
doToken( token, q );
//Open any extra brackets we might need.
if ( !betweenSpecialCase && EXPRESSION_OPENERS.contains( lcToken ) ) {
openExpression( q, lcToken );
}
//Cope with special cases of AND, NOT, )
specialCasesAfter( lcToken );
|
|