KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > hql > classic > QueryTranslatorImpl


1 //$Id: QueryTranslatorImpl.java,v 1.25 2005/06/22 04:19:31 oneovthafew Exp $
2
package org.hibernate.hql.classic;
3
4 import java.io.Serializable JavaDoc;
5 import java.lang.reflect.Constructor JavaDoc;
6 import java.sql.PreparedStatement JavaDoc;
7 import java.sql.ResultSet JavaDoc;
8 import java.sql.SQLException JavaDoc;
9 import java.util.ArrayList JavaDoc;
10 import java.util.HashMap JavaDoc;
11 import java.util.HashSet JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15 import java.util.Set JavaDoc;
16
17 import org.apache.commons.collections.SequencedHashMap;
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.hibernate.HibernateException;
21 import org.hibernate.LockMode;
22 import org.hibernate.MappingException;
23 import org.hibernate.QueryException;
24 import org.hibernate.ScrollableResults;
25 import org.hibernate.dialect.Dialect;
26 import org.hibernate.engine.JoinSequence;
27 import org.hibernate.engine.QueryParameters;
28 import org.hibernate.engine.SessionFactoryImplementor;
29 import org.hibernate.engine.SessionImplementor;
30 import org.hibernate.engine.TypedValue;
31 import org.hibernate.event.EventSource;
32 import org.hibernate.exception.JDBCExceptionHelper;
33 import org.hibernate.hql.FilterTranslator;
34 import org.hibernate.hql.HolderInstantiator;
35 import org.hibernate.hql.NameGenerator;
36 import org.hibernate.hql.QueryTranslator;
37 import org.hibernate.impl.IteratorImpl;
38 import org.hibernate.loader.BasicLoader;
39 import org.hibernate.persister.collection.CollectionPersister;
40 import org.hibernate.persister.collection.QueryableCollection;
41 import org.hibernate.persister.entity.Loadable;
42 import org.hibernate.persister.entity.PropertyMapping;
43 import org.hibernate.persister.entity.Queryable;
44 import org.hibernate.sql.ForUpdateFragment;
45 import org.hibernate.sql.JoinFragment;
46 import org.hibernate.sql.QuerySelect;
47 import org.hibernate.type.AssociationType;
48 import org.hibernate.type.EntityType;
49 import org.hibernate.type.Type;
50 import org.hibernate.type.TypeFactory;
51 import org.hibernate.util.ArrayHelper;
52 import org.hibernate.util.ReflectHelper;
53 import org.hibernate.util.StringHelper;
54
55 /**
56  * An instance of <tt>QueryTranslator</tt> translates a Hibernate
57  * query string to SQL.
58  */

59 public class QueryTranslatorImpl extends BasicLoader
60         implements QueryTranslator, FilterTranslator {
61
62     private final String JavaDoc queryString;
63
64     private final Map JavaDoc typeMap = new SequencedHashMap();
65     private final Map JavaDoc collections = new SequencedHashMap();
66     private List JavaDoc returnedTypes = new ArrayList JavaDoc();
67     private final List JavaDoc fromTypes = new ArrayList JavaDoc();
68     private final List JavaDoc scalarTypes = new ArrayList JavaDoc();
69     private final Map JavaDoc namedParameters = new HashMap JavaDoc();
70     private final Map JavaDoc aliasNames = new HashMap JavaDoc();
71     private final Map JavaDoc oneToOneOwnerNames = new HashMap JavaDoc();
72     private final Map JavaDoc uniqueKeyOwnerReferences = new HashMap JavaDoc();
73     private final Map JavaDoc decoratedPropertyMappings = new HashMap JavaDoc();
74
75     private final List JavaDoc scalarSelectTokens = new ArrayList JavaDoc();
76     private final List JavaDoc whereTokens = new ArrayList JavaDoc();
77     private final List JavaDoc havingTokens = new ArrayList JavaDoc();
78     private final Map JavaDoc joins = new SequencedHashMap();
79     private final List JavaDoc orderByTokens = new ArrayList JavaDoc();
80     private final List JavaDoc groupByTokens = new ArrayList JavaDoc();
81     private final Set JavaDoc querySpaces = new HashSet JavaDoc();
82     private final Set JavaDoc entitiesToFetch = new HashSet JavaDoc();
83
84     private final Map JavaDoc pathAliases = new HashMap JavaDoc();
85     private final Map JavaDoc pathJoins = new HashMap JavaDoc();
86
87     private Queryable[] persisters;
88     private int[] owners;
89     private EntityType[] ownerAssociationTypes;
90     private String JavaDoc[] names;
91     private boolean[] includeInSelect;
92     private int selectLength;
93     private Type[] returnTypes;
94     private Type[] actualReturnTypes;
95     private String JavaDoc[][] scalarColumnNames;
96     private Map JavaDoc tokenReplacements;
97     private int nameCount = 0;
98     private int parameterCount = 0;
99     private boolean distinct = false;
100     private boolean compiled;
101     private String JavaDoc sqlString;
102     private Class JavaDoc holderClass;
103     private Constructor JavaDoc holderConstructor;
104     private boolean hasScalars;
105     private boolean shallowQuery;
106     private QueryTranslatorImpl superQuery;
107
108     private QueryableCollection collectionPersister;
109     private int collectionOwnerColumn = -1;
110     private String JavaDoc collectionOwnerName;
111     private String JavaDoc fetchName;
112
113     private String JavaDoc[] suffixes;
114
115     private Map JavaDoc enabledFilters;
116
117     private static final Log log = LogFactory.getLog( QueryTranslatorImpl.class );
118
119     /**
120      * Construct a query translator
121      */

122     public QueryTranslatorImpl(
123             String JavaDoc queryString,
124             Map JavaDoc enabledFilters,
125             SessionFactoryImplementor factory) {
126         super( factory );
127         this.queryString = queryString;
128         this.enabledFilters = enabledFilters;
129     }
130
131     /**
132      * Compile a subquery
133      */

134     void compile(QueryTranslatorImpl superquery)
135             throws QueryException, MappingException {
136         this.tokenReplacements = superquery.tokenReplacements;
137         this.superQuery = superquery;
138         this.shallowQuery = true;
139         this.enabledFilters = superquery.getEnabledFilters();
140         compile();
141     }
142
143
144     /**
145      * Compile a "normal" query. This method may be called multiple
146      * times. Subsequent invocations are no-ops.
147      */

148     public synchronized void compile(Map JavaDoc replacements, boolean scalar)
149             throws QueryException, MappingException {
150         if ( !compiled ) {
151             this.tokenReplacements = replacements;
152             this.shallowQuery = scalar;
153             compile();
154         }
155     }
156
157     /**
158      * Compile a filter. This method may be called multiple
159      * times. Subsequent invocations are no-ops.
160      */

161     public synchronized void compile(String JavaDoc collectionRole, Map JavaDoc replacements, boolean scalar)
162             throws QueryException, MappingException {
163
164         if ( !isCompiled() ) {
165             addFromAssociation( "this", collectionRole );
166             compile( replacements, scalar );
167         }
168     }
169
170     /**
171      * Compile the query (generate the SQL).
172      */

173     private void compile() throws QueryException, MappingException {
174
175         log.trace( "compiling query" );
176         try {
177             ParserHelper.parse( new PreprocessingParser( tokenReplacements ),
178                     queryString,
179                     ParserHelper.HQL_SEPARATORS,
180                     this );
181             renderSQL();
182         }
183         catch ( QueryException qe ) {
184             qe.setQueryString( queryString );
185             throw qe;
186         }
187         catch ( MappingException me ) {
188             throw me;
189         }
190         catch ( Exception JavaDoc e ) {
191             log.debug( "unexpected query compilation problem", e );
192             e.printStackTrace();
193             QueryException qe = new QueryException( "Incorrect query syntax", e );
194             qe.setQueryString( queryString );
195             throw qe;
196         }
197
198         postInstantiate();
199
200         compiled = true;
201
202     }
203
204     public String JavaDoc getSQLString() {
205         return sqlString;
206     }
207
208     public String JavaDoc getQueryString() {
209         return queryString;
210     }
211
212     /**
213      * Persisters for the return values of a <tt>find()</tt> style query.
214      *
215      * @return an array of <tt>EntityPersister</tt>s.
216      */

217     protected Loadable[] getEntityPersisters() {
218         return persisters;
219     }
220
221     /**
222      * Types of the return values of an <tt>iterate()</tt> style query.
223      *
224      * @return an array of <tt>Type</tt>s.
225      */

226     public Type[] getReturnTypes() {
227         return actualReturnTypes;
228     }
229     
230     public String JavaDoc[] getReturnAliases() {
231         throw new UnsupportedOperationException JavaDoc("select clause aliases are not supported by classic parser");
232     }
233
234     public String JavaDoc[][] getColumnNames() {
235         return scalarColumnNames;
236     }
237
238     private static void logQuery(String JavaDoc hql, String JavaDoc sql) {
239         if ( log.isDebugEnabled() ) {
240             log.debug( "HQL: " + hql );
241             log.debug( "SQL: " + sql );
242         }
243     }
244
245     void setAliasName(String JavaDoc alias, String JavaDoc name) {
246         aliasNames.put( alias, name );
247     }
248
249     public String JavaDoc getAliasName(String JavaDoc alias) {
250         String JavaDoc name = ( String JavaDoc ) aliasNames.get( alias );
251         if ( name == null ) {
252             if ( superQuery != null ) {
253                 name = superQuery.getAliasName( alias );
254             }
255             else {
256                 name = alias;
257             }
258         }
259         return name;
260     }
261
262     String JavaDoc unalias(String JavaDoc path) {
263         String JavaDoc alias = StringHelper.root( path );
264         String JavaDoc name = getAliasName( alias );
265         if ( name != null ) {
266             return name + path.substring( alias.length() );
267         }
268         else {
269             return path;
270         }
271     }
272
273     void addEntityToFetch(String JavaDoc name, String JavaDoc oneToOneOwnerName, AssociationType ownerAssociationType) {
274         addEntityToFetch( name );
275         if ( oneToOneOwnerName != null ) oneToOneOwnerNames.put( name, oneToOneOwnerName );
276         if ( ownerAssociationType != null ) uniqueKeyOwnerReferences.put( name, ownerAssociationType );
277     }
278
279     private void addEntityToFetch(String JavaDoc name) {
280         entitiesToFetch.add( name );
281     }
282
283     private int nextCount() {
284         return ( superQuery == null ) ? nameCount++ : superQuery.nameCount++;
285     }
286
287     String JavaDoc createNameFor(String JavaDoc type) {
288         return StringHelper.generateAlias( type, nextCount() );
289     }
290
291     String JavaDoc createNameForCollection(String JavaDoc role) {
292         return StringHelper.generateAlias( role, nextCount() );
293     }
294
295     private String JavaDoc getType(String JavaDoc name) {
296         String JavaDoc type = ( String JavaDoc ) typeMap.get( name );
297         if ( type == null && superQuery != null ) {
298             type = superQuery.getType( name );
299         }
300         return type;
301     }
302
303     private String JavaDoc getRole(String JavaDoc name) {
304         String JavaDoc role = ( String JavaDoc ) collections.get( name );
305         if ( role == null && superQuery != null ) {
306             role = superQuery.getRole( name );
307         }
308         return role;
309     }
310
311     boolean isName(String JavaDoc name) {
312         return aliasNames.containsKey( name ) ||
313                 typeMap.containsKey( name ) ||
314                 collections.containsKey( name ) || (
315                 superQuery != null && superQuery.isName( name )
316                 );
317     }
318
319     PropertyMapping getPropertyMapping(String JavaDoc name) throws QueryException {
320         PropertyMapping decorator = getDecoratedPropertyMapping( name );
321         if ( decorator != null ) return decorator;
322
323         String JavaDoc type = getType( name );
324         if ( type == null ) {
325             String JavaDoc role = getRole( name );
326             if ( role == null ) {
327                 throw new QueryException( "alias not found: " + name );
328             }
329             return getCollectionPersister( role ); //.getElementPropertyMapping();
330
}
331         else {
332             Queryable persister = getEntityPersister( type );
333             if ( persister == null ) throw new QueryException( "persistent class not found: " + type );
334             return persister;
335         }
336     }
337
338     private PropertyMapping getDecoratedPropertyMapping(String JavaDoc name) {
339         return ( PropertyMapping ) decoratedPropertyMappings.get( name );
340     }
341
342     void decoratePropertyMapping(String JavaDoc name, PropertyMapping mapping) {
343         decoratedPropertyMappings.put( name, mapping );
344     }
345
346     private Queryable getEntityPersisterForName(String JavaDoc name) throws QueryException {
347         String JavaDoc type = getType( name );
348         Queryable persister = getEntityPersister( type );
349         if ( persister == null ) throw new QueryException( "persistent class not found: " + type );
350         return persister;
351     }
352
353     Queryable getEntityPersisterUsingImports(String JavaDoc className) {
354         final String JavaDoc importedClassName = getFactory().getImportedClassName( className );
355         if ( importedClassName == null ) {
356             return null;
357         }
358         try {
359             return ( Queryable ) getFactory().getEntityPersister( importedClassName );
360         }
361         catch ( MappingException me ) {
362             return null;
363         }
364     }
365
366     Queryable getEntityPersister(String JavaDoc entityName) throws QueryException {
367         try {
368             return ( Queryable ) getFactory().getEntityPersister( entityName );
369         }
370         catch ( Exception JavaDoc e ) {
371             throw new QueryException( "persistent class not found: " + entityName );
372         }
373     }
374
375     QueryableCollection getCollectionPersister(String JavaDoc role) throws QueryException {
376         try {
377             return ( QueryableCollection ) getFactory().getCollectionPersister( role );
378         }
379         catch ( ClassCastException JavaDoc cce ) {
380             throw new QueryException( "collection role is not queryable: " + role );
381         }
382         catch ( Exception JavaDoc e ) {
383             throw new QueryException( "collection role not found: " + role );
384         }
385     }
386
387     void addType(String JavaDoc name, String JavaDoc type) {
388         typeMap.put( name, type );
389     }
390
391     void addCollection(String JavaDoc name, String JavaDoc role) {
392         collections.put( name, role );
393     }
394
395     void addFrom(String JavaDoc name, String JavaDoc type, JoinSequence joinSequence)
396             throws QueryException {
397         addType( name, type );
398         addFrom( name, joinSequence );
399     }
400
401     void addFromCollection(String JavaDoc name, String JavaDoc collectionRole, JoinSequence joinSequence)
402             throws QueryException {
403         //register collection role
404
addCollection( name, collectionRole );
405         addJoin( name, joinSequence );
406     }
407
408     void addFrom(String JavaDoc name, JoinSequence joinSequence)
409             throws QueryException {
410         fromTypes.add( name );
411         addJoin( name, joinSequence );
412     }
413
414     void addFromClass(String JavaDoc name, Queryable classPersister)
415             throws QueryException {
416         JoinSequence joinSequence = new JoinSequence( getFactory() )
417                 .setRoot( classPersister, name );
418         //crossJoins.add(name);
419
addFrom( name, classPersister.getEntityName(), joinSequence );
420     }
421
422     void addSelectClass(String JavaDoc name) {
423         returnedTypes.add( name );
424     }
425
426     void addSelectScalar(Type type) {
427         scalarTypes.add( type );
428     }
429
430     void appendWhereToken(String JavaDoc token) {
431         whereTokens.add( token );
432     }
433
434     void appendHavingToken(String JavaDoc token) {
435         havingTokens.add( token );
436     }
437
438     void appendOrderByToken(String JavaDoc token) {
439         orderByTokens.add( token );
440     }
441
442     void appendGroupByToken(String JavaDoc token) {
443         groupByTokens.add( token );
444     }
445
446     void appendScalarSelectToken(String JavaDoc token) {
447         scalarSelectTokens.add( token );
448     }
449
450     void appendScalarSelectTokens(String JavaDoc[] tokens) {
451         scalarSelectTokens.add( tokens );
452     }
453
454     void addFromJoinOnly(String JavaDoc name, JoinSequence joinSequence) throws QueryException {
455         addJoin( name, joinSequence.getFromPart() );
456     }
457
458     void addJoin(String JavaDoc name, JoinSequence joinSequence) throws QueryException {
459         if ( !joins.containsKey( name ) ) joins.put( name, joinSequence );
460     }
461
462     void addNamedParameter(String JavaDoc name) {
463         if ( superQuery != null ) superQuery.addNamedParameter( name );
464         Integer JavaDoc loc = new Integer JavaDoc( parameterCount++ );
465         Object JavaDoc o = namedParameters.get( name );
466         if ( o == null ) {
467             namedParameters.put( name, loc );
468         }
469         else if ( o instanceof Integer JavaDoc ) {
470             ArrayList JavaDoc list = new ArrayList JavaDoc( 4 );
471             list.add( o );
472             list.add( loc );
473             namedParameters.put( name, list );
474         }
475         else {
476             ( ( ArrayList JavaDoc ) o ).add( loc );
477         }
478     }
479
480     public int[] getNamedParameterLocs(String JavaDoc name) throws QueryException {
481         Object JavaDoc o = namedParameters.get( name );
482         if ( o == null ) {
483             QueryException qe = new QueryException( ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name );
484             qe.setQueryString( queryString );
485             throw qe;
486         }
487         if ( o instanceof Integer JavaDoc ) {
488             return new int[]{( ( Integer JavaDoc ) o ).intValue()};
489         }
490         else {
491             return ArrayHelper.toIntArray( ( ArrayList JavaDoc ) o );
492         }
493     }
494
495     private void renderSQL() throws QueryException, MappingException {
496
497         final int rtsize;
498         if ( returnedTypes.size() == 0 && scalarTypes.size() == 0 ) {
499             //ie no select clause in HQL
500
returnedTypes = fromTypes;
501             rtsize = returnedTypes.size();
502         }
503         else {
504             rtsize = returnedTypes.size();
505             Iterator JavaDoc iter = entitiesToFetch.iterator();
506             while ( iter.hasNext() ) {
507                 returnedTypes.add( iter.next() );
508             }
509         }
510         int size = returnedTypes.size();
511         persisters = new Queryable[size];
512         names = new String JavaDoc[size];
513         owners = new int[size];
514         ownerAssociationTypes = new EntityType[size];
515         suffixes = new String JavaDoc[size];
516         includeInSelect = new boolean[size];
517         for ( int i = 0; i < size; i++ ) {
518             String JavaDoc name = ( String JavaDoc ) returnedTypes.get( i );
519             //if ( !isName(name) ) throw new QueryException("unknown type: " + name);
520
persisters[i] = getEntityPersisterForName( name );
521             // TODO: cannot use generateSuffixes() - it handles the initial suffix differently.
522
suffixes[i] = ( size == 1 ) ? "" : Integer.toString( i ) + '_';
523             names[i] = name;
524             includeInSelect[i] = !entitiesToFetch.contains( name );
525             if ( includeInSelect[i] ) selectLength++;
526             if ( name.equals( collectionOwnerName ) ) collectionOwnerColumn = i;
527             String JavaDoc oneToOneOwner = ( String JavaDoc ) oneToOneOwnerNames.get( name );
528             owners[i] = ( oneToOneOwner == null ) ? -1 : returnedTypes.indexOf( oneToOneOwner );
529             ownerAssociationTypes[i] = (EntityType) uniqueKeyOwnerReferences.get( name );
530         }
531
532         if ( ArrayHelper.isAllNegative( owners ) ) owners = null;
533
534         String JavaDoc scalarSelect = renderScalarSelect(); //Must be done here because of side-effect! yuck...
535

536         int scalarSize = scalarTypes.size();
537         hasScalars = scalarTypes.size() != rtsize;
538
539         returnTypes = new Type[scalarSize];
540         for ( int i = 0; i < scalarSize; i++ ) {
541             returnTypes[i] = ( Type ) scalarTypes.get( i );
542         }
543
544         QuerySelect sql = new QuerySelect( getFactory().getDialect() );
545         sql.setDistinct( distinct );
546
547         if ( !shallowQuery ) {
548             renderIdentifierSelect( sql );
549             renderPropertiesSelect( sql );
550         }
551
552         if ( collectionPersister != null ) {
553             sql.addSelectFragmentString( collectionPersister.selectFragment( fetchName, "__" ) );
554         }
555
556         if ( hasScalars || shallowQuery ) sql.addSelectFragmentString( scalarSelect );
557
558         //TODO: for some dialects it would be appropriate to add the renderOrderByPropertiesSelect() to other select strings
559
mergeJoins( sql.getJoinFragment() );
560
561         sql.setWhereTokens( whereTokens.iterator() );
562
563         sql.setGroupByTokens( groupByTokens.iterator() );
564         sql.setHavingTokens( havingTokens.iterator() );
565         sql.setOrderByTokens( orderByTokens.iterator() );
566
567         if ( collectionPersister != null && collectionPersister.hasOrdering() ) {
568             sql.addOrderBy( collectionPersister.getSQLOrderByString( fetchName ) );
569         }
570
571         scalarColumnNames = NameGenerator.generateColumnNames( returnTypes, getFactory() );
572
573         // initialize the Set of queried identifier spaces (ie. tables)
574
Iterator JavaDoc iter = collections.values().iterator();
575         while ( iter.hasNext() ) {
576             CollectionPersister p = getCollectionPersister( ( String JavaDoc ) iter.next() );
577             addQuerySpaces( p.getCollectionSpaces() );
578         }
579         iter = typeMap.keySet().iterator();
580         while ( iter.hasNext() ) {
581             Queryable p = getEntityPersisterForName( ( String JavaDoc ) iter.next() );
582             addQuerySpaces( p.getQuerySpaces() );
583         }
584
585         sqlString = sql.toQueryString();
586
587         if ( holderClass != null ) holderConstructor = ReflectHelper.getConstructor( holderClass, returnTypes );
588
589         if ( hasScalars ) {
590             actualReturnTypes = returnTypes;
591         }
592         else {
593             actualReturnTypes = new Type[selectLength];
594             int j = 0;
595             for ( int i = 0; i < persisters.length; i++ ) {
596                 if ( includeInSelect[i] ) {
597                     actualReturnTypes[j++] = TypeFactory.manyToOne( persisters[i].getEntityName(), shallowQuery );
598                 }
599             }
600         }
601
602     }
603
604     private void renderIdentifierSelect(QuerySelect sql) {
605         int size = returnedTypes.size();
606
607         for ( int k = 0; k < size; k++ ) {
608             String JavaDoc name = ( String JavaDoc ) returnedTypes.get( k );
609             String JavaDoc suffix = size == 1 ? "" : Integer.toString( k ) + '_';
610             sql.addSelectFragmentString( persisters[k].identifierSelectFragment( name, suffix ) );
611         }
612
613     }
614
615     /*private String renderOrderByPropertiesSelect() {
616         StringBuffer buf = new StringBuffer(10);
617
618         //add the columns we are ordering by to the select ID select clause
619         Iterator iter = orderByTokens.iterator();
620         while ( iter.hasNext() ) {
621             String token = (String) iter.next();
622             if ( token.lastIndexOf(".") > 0 ) {
623                 //ie. it is of form "foo.bar", not of form "asc" or "desc"
624                 buf.append(StringHelper.COMMA_SPACE).append(token);
625             }
626         }
627
628         return buf.toString();
629     }*/

630
631     private void renderPropertiesSelect(QuerySelect sql) {
632         int size = returnedTypes.size();
633         for ( int k = 0; k < size; k++ ) {
634             String JavaDoc suffix = size == 1 ? "" : Integer.toString( k ) + '_';
635             String JavaDoc name = ( String JavaDoc ) returnedTypes.get( k );
636             sql.addSelectFragmentString( persisters[k].propertySelectFragment( name, suffix, false ) );
637         }
638     }
639
640     /**
641      * WARNING: side-effecty
642      */

643     private String JavaDoc renderScalarSelect() {
644
645         boolean isSubselect = superQuery != null;
646
647         StringBuffer JavaDoc buf = new StringBuffer JavaDoc( 20 );
648
649         if ( scalarTypes.size() == 0 ) {
650             //ie. no select clause
651
int size = returnedTypes.size();
652             for ( int k = 0; k < size; k++ ) {
653
654                 scalarTypes.add( TypeFactory.manyToOne( persisters[k].getEntityName(), shallowQuery ) );
655
656                 String JavaDoc[] idColumnNames = persisters[k].getIdentifierColumnNames();
657                 for ( int i = 0; i < idColumnNames.length; i++ ) {
658                     buf.append( returnedTypes.get( k ) ).append( '.' ).append( idColumnNames[i] );
659                     if ( !isSubselect ) buf.append( " as " ).append( NameGenerator.scalarName( k, i ) );
660                     if ( i != idColumnNames.length - 1 || k != size - 1 ) buf.append( ", " );
661                 }
662
663             }
664
665         }
666         else {
667             //there _was_ a select clause
668
Iterator JavaDoc iter = scalarSelectTokens.iterator();
669             int c = 0;
670             boolean nolast = false; //real hacky...
671
int parenCount = 0; // used to count the nesting of parentheses
672
while ( iter.hasNext() ) {
673                 Object JavaDoc next = iter.next();
674                 if ( next instanceof String JavaDoc ) {
675                     String JavaDoc token = ( String JavaDoc ) next;
676
677                     if ( "(".equals( token ) ) {
678                         parenCount++;
679                     }
680                     else if ( ")".equals( token ) ) {
681                         parenCount--;
682                     }
683
684                     String JavaDoc lc = token.toLowerCase();
685                     if ( lc.equals( ", " ) ) {
686                         if ( nolast ) {
687                             nolast = false;
688                         }
689                         else {
690                             if ( !isSubselect && parenCount == 0 ) {
691                                 int x = c++;
692                                 buf.append( " as " )
693                                         .append( NameGenerator.scalarName( x, 0 ) );
694                             }
695                         }
696                     }
697                     buf.append( token );
698                     if ( lc.equals( "distinct" ) || lc.equals( "all" ) ) {
699                         buf.append( ' ' );
700                     }
701                 }
702                 else {
703                     nolast = true;
704                     String JavaDoc[] tokens = ( String JavaDoc[] ) next;
705                     for ( int i = 0; i < tokens.length; i++ ) {
706                         buf.append( tokens[i] );
707                         if ( !isSubselect ) {
708                             buf.append( " as " )
709                                     .append( NameGenerator.scalarName( c, i ) );
710                         }
711                         if ( i != tokens.length - 1 ) buf.append( ", " );
712                     }
713                     c++;
714                 }
715             }
716             if ( !isSubselect && !nolast ) {
717                 int x = c++;
718                 buf.append( " as " )
719                         .append( NameGenerator.scalarName( x, 0 ) );
720             }
721
722         }
723
724         return buf.toString();
725     }
726
727     private void mergeJoins(JoinFragment ojf) throws MappingException, QueryException {
728
729         Iterator JavaDoc iter = joins.entrySet().iterator();
730         while ( iter.hasNext() ) {
731             Map.Entry JavaDoc me = ( Map.Entry JavaDoc ) iter.next();
732             String JavaDoc name = ( String JavaDoc ) me.getKey();
733             JoinSequence join = ( JoinSequence ) me.getValue();
734             join.setSelector( new JoinSequence.Selector() {
735                 public boolean includeSubclasses(String JavaDoc alias) {
736                     boolean include = returnedTypes.contains( alias ) && !isShallowQuery();
737                     return include;
738                 }
739             } );
740
741             if ( typeMap.containsKey( name ) ) {
742                 ojf.addFragment( join.toJoinFragment( enabledFilters, true ) );
743             }
744             else if ( collections.containsKey( name ) ) {
745                 ojf.addFragment( join.toJoinFragment( enabledFilters, true ) );
746             }
747             else {
748                 //name from a super query (a bit inelegant that it shows up here)
749
}
750
751         }
752
753     }
754
755     public final Set JavaDoc getQuerySpaces() {
756         return querySpaces;
757     }
758
759     /**
760      * Is this query called by scroll() or iterate()?
761      *
762      * @return true if it is, false if it is called by find() or list()
763      */

764     boolean isShallowQuery() {
765         return shallowQuery;
766     }
767
768     void addQuerySpaces(Serializable JavaDoc[] spaces) {
769         for ( int i = 0; i < spaces.length; i++ ) {
770             querySpaces.add( spaces[i] );
771         }
772         if ( superQuery != null ) superQuery.addQuerySpaces( spaces );
773     }
774
775     void setDistinct(boolean distinct) {
776         this.distinct = distinct;
777     }
778
779     boolean isSubquery() {
780         return superQuery != null;
781     }
782
783     /**
784      * Overrides method from Loader
785      */

786     public CollectionPersister[] getCollectionPersisters() {
787         return collectionPersister == null ? null : new CollectionPersister[] { collectionPersister };
788     }
789
790     protected String JavaDoc[] getCollectionSuffixes() {
791         return collectionPersister == null ? null : new String JavaDoc[] { "__" };
792     }
793
794     void setCollectionToFetch(String JavaDoc role, String JavaDoc name, String JavaDoc ownerName, String JavaDoc entityName)
795             throws QueryException {
796         fetchName = name;
797         collectionPersister = getCollectionPersister( role );
798         collectionOwnerName = ownerName;
799         if ( collectionPersister.getElementType().isEntityType() ) {
800             addEntityToFetch( entityName );
801         }
802     }
803
804     protected String JavaDoc[] getSuffixes() {
805         return suffixes;
806     }
807
808     protected String JavaDoc[] getAliases() {
809         return names;
810     }
811
812     /**
813      * Used for collection filters
814      */

815     private void addFromAssociation(final String JavaDoc elementName, final String JavaDoc collectionRole)
816             throws QueryException {
817         //q.addCollection(collectionName, collectionRole);
818
QueryableCollection persister = getCollectionPersister( collectionRole );
819         Type collectionElementType = persister.getElementType();
820         if ( !collectionElementType.isEntityType() ) {
821             throw new QueryException( "collection of values in filter: " + elementName );
822         }
823
824         String JavaDoc[] keyColumnNames = persister.getKeyColumnNames();
825         //if (keyColumnNames.length!=1) throw new QueryException("composite-key collection in filter: " + collectionRole);
826

827         String JavaDoc collectionName;
828         JoinSequence join = new JoinSequence( getFactory() );
829         collectionName = persister.isOneToMany() ?
830                 elementName :
831                 createNameForCollection( collectionRole );
832         join.setRoot( persister, collectionName );
833         if ( !persister.isOneToMany() ) {
834             //many-to-many
835
addCollection( collectionName, collectionRole );
836             try {
837                 join.addJoin( ( AssociationType ) persister.getElementType(),
838                         elementName,
839                         JoinFragment.INNER_JOIN,
840                         persister.getElementColumnNames(collectionName) );
841             }
842             catch ( MappingException me ) {
843                 throw new QueryException( me );
844             }
845         }
846         join.addCondition( collectionName, keyColumnNames, " = ?" );
847         //if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(collectionName) );
848
EntityType elemType = ( EntityType ) collectionElementType;
849         addFrom( elementName, elemType.getAssociatedEntityName(), join );
850
851     }
852
853     String JavaDoc getPathAlias(String JavaDoc path) {
854         return ( String JavaDoc ) pathAliases.get( path );
855     }
856
857     JoinSequence getPathJoin(String JavaDoc path) {
858         return ( JoinSequence ) pathJoins.get( path );
859     }
860
861     void addPathAliasAndJoin(String JavaDoc path, String JavaDoc alias, JoinSequence joinSequence) {
862         pathAliases.put( path, alias );
863         pathJoins.put( path, joinSequence );
864     }
865
866     protected int bindNamedParameters(PreparedStatement JavaDoc ps, Map JavaDoc namedParams, int start, SessionImplementor session)
867             throws SQLException JavaDoc, HibernateException {
868         if ( namedParams != null ) {
869             // assumes that types are all of span 1
870
Iterator JavaDoc iter = namedParams.entrySet().iterator();
871             int result = 0;
872             while ( iter.hasNext() ) {
873                 Map.Entry JavaDoc e = ( Map.Entry JavaDoc ) iter.next();
874                 String JavaDoc name = ( String JavaDoc ) e.getKey();
875                 TypedValue typedval = ( TypedValue ) e.getValue();
876                 int[] locs = getNamedParameterLocs( name );
877                 for ( int i = 0; i < locs.length; i++ ) {
878                     typedval.getType().nullSafeSet( ps, typedval.getValue(), locs[i] + start, session );
879                 }
880                 result += locs.length;
881             }
882             return result;
883         }
884         else {
885             return 0;
886         }
887     }
888
889     public List JavaDoc list(SessionImplementor session, QueryParameters queryParameters)
890             throws HibernateException {
891         return list( session, queryParameters, getQuerySpaces(), actualReturnTypes );
892     }
893
894     /**
895      * Return the query results as an iterator
896      */

897     public Iterator JavaDoc iterate(QueryParameters queryParameters, EventSource session)
898             throws HibernateException {
899
900         boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
901         long startTime = 0;
902         if ( stats ) startTime = System.currentTimeMillis();
903
904         try {
905
906             PreparedStatement JavaDoc st = prepareQueryStatement( queryParameters, false, session );
907             ResultSet JavaDoc rs = getResultSet( st, false, queryParameters.getRowSelection(), session );
908             HolderInstantiator hi = new HolderInstantiator(holderConstructor, false, false, null);
909             Iterator JavaDoc result = new IteratorImpl( rs, st, session, returnTypes, getColumnNames(), hi );
910
911             if ( stats ) {
912                 session.getFactory().getStatisticsImplementor().queryExecuted(
913                         "HQL: " + queryString,
914                         0,
915                         System.currentTimeMillis() - startTime );
916             }
917
918             return result;
919
920         }
921         catch ( SQLException JavaDoc sqle ) {
922             throw JDBCExceptionHelper.convert(
923                     getFactory().getSQLExceptionConverter(),
924                     sqle,
925                     "could not execute query using iterate",
926                     getSQLString()
927                 );
928         }
929
930     }
931
932     public int executeUpdate(QueryParameters queryParameters, SessionImplementor session) throws HibernateException {
933         throw new UnsupportedOperationException JavaDoc( "Not supported! Use the AST translator...");
934     }
935
936     protected Object JavaDoc getResultColumnOrRow(Object JavaDoc[] row, ResultSet JavaDoc rs, SessionImplementor session)
937             throws SQLException JavaDoc, HibernateException {
938         row = toResultRow( row );
939         if ( hasScalars ) {
940             String JavaDoc[][] scalarColumns = getColumnNames();
941             int queryCols = returnTypes.length;
942             if ( holderClass == null && queryCols == 1 ) {
943                 return returnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null );
944             }
945             else {
946                 row = new Object JavaDoc[queryCols];
947                 for ( int i = 0; i < queryCols; i++ )
948                     row[i] = returnTypes[i].nullSafeGet( rs, scalarColumns[i], session, null );
949                 return row;
950             }
951         }
952         else if ( holderClass == null ) {
953             return row.length == 1 ? row[0] : row;
954         }
955         else {
956             return row;
957         }
958
959     }
960
961     protected List JavaDoc getResultList(List JavaDoc results) throws QueryException {
962         if ( holderClass != null ) {
963             for ( int i = 0; i < results.size(); i++ ) {
964                 Object JavaDoc[] row = ( Object JavaDoc[] ) results.get( i );
965                 try {
966                     results.set( i, holderConstructor.newInstance( row ) );
967                 }
968                 catch ( Exception JavaDoc e ) {
969                     throw new QueryException( "could not instantiate: " + holderClass, e );
970                 }
971             }
972         }
973         return results;
974     }
975
976     private Object JavaDoc[] toResultRow(Object JavaDoc[] row) {
977         if ( selectLength == row.length ) {
978             return row;
979         }
980         else {
981             Object JavaDoc[] result = new Object JavaDoc[selectLength];
982             int j = 0;
983             for ( int i = 0; i < row.length; i++ ) {
984                 if ( includeInSelect[i] ) result[j++] = row[i];
985             }
986             return result;
987         }
988     }
989
990     void setHolderClass(Class JavaDoc clazz) {
991         holderClass = clazz;
992     }
993
994     protected LockMode[] getLockModes(Map JavaDoc lockModes) {
995         // unfortunately this stuff can't be cached because
996
// it is per-invocation, not constant for the
997
// QueryTranslator instance
998
HashMap JavaDoc nameLockModes = new HashMap JavaDoc();
999         if ( lockModes != null ) {
1000            Iterator JavaDoc iter = lockModes.entrySet().iterator();
1001            while ( iter.hasNext() ) {
1002                Map.Entry JavaDoc me = ( Map.Entry JavaDoc ) iter.next();
1003                nameLockModes.put( getAliasName( ( String JavaDoc ) me.getKey() ),
1004                        me.getValue() );
1005            }
1006        }
1007        LockMode[] lockModeArray = new LockMode[names.length];
1008        for ( int i = 0; i < names.length; i++ ) {
1009            LockMode lm = ( LockMode ) nameLockModes.get( names[i] );
1010            if ( lm == null ) lm = LockMode.NONE;
1011            lockModeArray[i] = lm;
1012        }
1013        return lockModeArray;
1014    }
1015
1016    protected String JavaDoc applyLocks(String JavaDoc sql, Map JavaDoc lockModes, Dialect dialect) throws QueryException {
1017        // can't cache this stuff either (per-invocation)
1018
final String JavaDoc result;
1019        if ( lockModes == null || lockModes.size() == 0 ) {
1020            result = sql;
1021        }
1022        else {
1023            Map JavaDoc aliasedLockModes = new HashMap JavaDoc();
1024            Iterator JavaDoc iter = lockModes.entrySet().iterator();
1025            while ( iter.hasNext() ) {
1026                Map.Entry JavaDoc me = ( Map.Entry JavaDoc ) iter.next();
1027                aliasedLockModes.put( getAliasName( ( String JavaDoc ) me.getKey() ), me.getValue() );
1028            }
1029            Map JavaDoc keyColumnNames = null;
1030            if ( dialect.forUpdateOfColumns() ) {
1031                keyColumnNames = new HashMap JavaDoc();
1032                for ( int i = 0; i < names.length; i++ ) {
1033                    keyColumnNames.put( names[i], persisters[i].getIdentifierColumnNames() );
1034                }
1035            }
1036            result = sql + new ForUpdateFragment( dialect, aliasedLockModes, keyColumnNames ).toFragmentString();
1037        }
1038        logQuery( queryString, result );
1039        return result;
1040    }
1041
1042    protected boolean upgradeLocks() {
1043        return true;
1044    }
1045
1046    protected int[] getCollectionOwners() {
1047        return new int[] { collectionOwnerColumn };
1048    }
1049
1050    protected boolean isCompiled() {
1051        return compiled;
1052    }
1053
1054    public String JavaDoc toString() {
1055        return queryString;
1056    }
1057
1058    protected int[] getOwners() {
1059        return owners;
1060    }
1061
1062    protected EntityType[] getOwnerAssociationTypes() {
1063        return ownerAssociationTypes;
1064    }
1065
1066    public Class JavaDoc getHolderClass() {
1067        return holderClass;
1068    }
1069
1070    public Map JavaDoc getEnabledFilters() {
1071        return enabledFilters;
1072    }
1073
1074    public ScrollableResults scroll(final QueryParameters queryParameters,
1075                                    final SessionImplementor session)
1076            throws HibernateException {
1077        HolderInstantiator hi = new HolderInstantiator(holderConstructor, false, false, null);
1078        return scroll( queryParameters, returnTypes, hi, session );
1079    }
1080
1081    protected String JavaDoc getQueryIdentifier() {
1082        return queryString;
1083    }
1084
1085    protected boolean isSubselectLoadingEnabled() {
1086        return hasSubselectLoadableCollections();
1087    }
1088
1089    public void validateScrollability() throws HibernateException {
1090        // This is the legacy behaviour for HQL queries...
1091
if ( getCollectionPersisters() != null ) {
1092            throw new HibernateException( "Cannot scroll queries which initialize collections" );
1093        }
1094    }
1095
1096    public boolean containsCollectionFetches() {
1097        return false;
1098    }
1099}
1100
Popular Tags