KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > test > hql > QueryTranslatorTestCase


1 // $Id: QueryTranslatorTestCase.java,v 1.30 2005/07/14 18:47:33 steveebersole Exp $
2
package org.hibernate.test.hql;
3
4 import java.sql.Connection JavaDoc;
5 import java.sql.ParameterMetaData JavaDoc;
6 import java.sql.PreparedStatement JavaDoc;
7 import java.sql.ResultSet JavaDoc;
8 import java.sql.ResultSetMetaData JavaDoc;
9 import java.sql.SQLException JavaDoc;
10 import java.util.Collections JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.Set JavaDoc;
15 import java.util.StringTokenizer JavaDoc;
16 import java.util.TreeMap JavaDoc;
17
18 import junit.framework.ComparisonFailure;
19
20 import org.hibernate.EntityMode;
21 import org.hibernate.MappingException;
22 import org.hibernate.QueryException;
23 import org.hibernate.classic.Session;
24 import org.hibernate.engine.SessionFactoryImplementor;
25 import org.hibernate.hql.QueryTranslator;
26 import org.hibernate.hql.QueryTranslatorFactory;
27 import org.hibernate.hql.ast.ASTQueryTranslatorFactory;
28 import org.hibernate.hql.ast.HqlToken;
29 import org.hibernate.hql.ast.util.ASTPrinter;
30 import org.hibernate.hql.classic.ClassicQueryTranslatorFactory;
31 import org.hibernate.test.TestCase;
32 import org.hibernate.type.Type;
33 import org.hibernate.type.TypeFactory;
34 import org.hibernate.util.StringHelper;
35
36 /**
37  * Test case superclass for testing QueryTranslator implementations.
38  *
39  * @author josh Dec 6, 2004 8:21:21 AM
40  */

41 public abstract class QueryTranslatorTestCase extends TestCase {
42     public QueryTranslatorTestCase(String JavaDoc x) {
43         super( x );
44         // Create an instance of HqlToken, so that it will have an entry point outside the package. This
45
// will stop IDEA's code inspector from suggesting that HqlToken should be package local.
46
new HqlToken();
47     }
48
49     public void assertTranslation(String JavaDoc hql) throws QueryException, MappingException {
50         assertTranslation( hql, null );
51     }
52
53     public void assertTranslation(String JavaDoc hql, boolean scalar) throws QueryException, MappingException {
54         assertTranslation( hql, null, scalar, null );
55     }
56
57     protected void assertTranslation(String JavaDoc hql, HashMap JavaDoc replacements) {
58         ComparisonFailure cf = null;
59         try {
60             assertTranslation( hql, replacements, false, null );
61         }
62         catch ( ComparisonFailure e ) {
63             e.printStackTrace();
64             cf = e;
65         }
66         if ("false".equals(System.getProperty("org.hibernate.test.hql.SkipScalarQuery","false"))) {
67             // Run the scalar translation anyway, even if there was a comparison failure.
68
assertTranslation( hql, replacements, true, null );
69         }
70         if (cf != null)
71             throw cf;
72     }
73
74     protected void runClassicTranslator(String JavaDoc hql) throws Exception JavaDoc {
75         SessionFactoryImplementor factory = getSessionFactoryImplementor();
76         Map JavaDoc replacements = new HashMap JavaDoc();
77         QueryTranslator oldQueryTranslator = null;
78         try {
79             QueryTranslatorFactory classic = new ClassicQueryTranslatorFactory();
80             oldQueryTranslator = classic.createQueryTranslator( hql, Collections.EMPTY_MAP, factory );
81             oldQueryTranslator.compile( replacements, false );
82         }
83         catch ( Exception JavaDoc e ) {
84             e.printStackTrace();
85             throw e;
86         }
87         String JavaDoc oldsql = oldQueryTranslator.getSQLString();
88         System.out.println( "HQL : " + hql );
89         System.out.println( "OLD SQL: " + oldsql );
90     }
91
92     protected void assertTranslation(String JavaDoc hql, HashMap JavaDoc replacements, boolean scalar, String JavaDoc sql) {
93         SessionFactoryImplementor factory = getSessionFactoryImplementor();
94
95         // Create an empty replacements map if we don't have one.
96
if ( replacements == null ) {
97             replacements = new HashMap JavaDoc();
98         }
99
100         // steve -> note that the empty maps here represent the currently enabled filters...
101
QueryTranslator oldQueryTranslator = null;
102         Exception JavaDoc oldException = null;
103         try {
104             System.out.println("Compiling with classic QueryTranslator...");
105             QueryTranslatorFactory classic = new ClassicQueryTranslatorFactory();
106             oldQueryTranslator = classic.createQueryTranslator( hql, Collections.EMPTY_MAP, factory );
107             oldQueryTranslator.compile( replacements, scalar );
108         }
109         catch ( QueryException e ) {
110             oldException = e;
111         }
112         catch ( MappingException e ) {
113             oldException = e;
114         }
115
116         QueryTranslator newQueryTranslator = null;
117         Exception JavaDoc newException = null;
118         try {
119             System.out.println("Compiling with AST QueryTranslator...");
120             QueryTranslatorFactory ast = new ASTQueryTranslatorFactory();
121             newQueryTranslator = ast.createQueryTranslator( hql, Collections.EMPTY_MAP, factory );
122             newQueryTranslator.compile( replacements, scalar );
123         }
124         catch ( QueryException e ) {
125             newException = e;
126         }
127         catch ( MappingException e ) {
128             newException = e;
129         }
130
131         // If the old QT threw an exception, the new one should too.
132
if ( oldException != null ) {
133 // oldException.printStackTrace();
134
assertNotNull( "New query translator did *NOT* throw an exception, the old one did : " + oldException, newException );
135             assertEquals( oldException.getMessage(), newException.getMessage() );
136             return; // Don't bother with the rest of the assertions.
137
}
138         else if ( newException != null ) {
139             newException.printStackTrace();
140             assertNull( "Old query translator did not throw an exception, the new one did", newException );
141         }
142
143         // -- check all of the outputs --
144
checkSql( oldQueryTranslator, newQueryTranslator, hql, scalar, sql );
145         checkQuerySpaces( oldQueryTranslator, newQueryTranslator );
146         checkReturnedTypes( oldQueryTranslator, newQueryTranslator );
147         checkColumnNames( oldQueryTranslator, newQueryTranslator );
148
149     }
150
151     protected SessionFactoryImplementor getSessionFactoryImplementor() {
152         SessionFactoryImplementor factory = ( SessionFactoryImplementor ) getSessions();
153         if ( factory == null ) {
154             throw new NullPointerException JavaDoc( "Unable to create factory!" );
155         }
156         return factory;
157     }
158
159     private void checkColumnNames(QueryTranslator oldQueryTranslator, QueryTranslator newQueryTranslator) {
160         // Check the column names.
161

162         String JavaDoc[][] oldColumnNames = oldQueryTranslator.getColumnNames();
163         String JavaDoc[][] newColumnNames = newQueryTranslator.getColumnNames();
164         /*assertEquals( "Column name array is not the right length!", oldColumnNames.length, newColumnNames.length );
165         for ( int i = 0; i < oldColumnNames.length; i++ ) {
166             assertEquals( "Column name array [" + i + "] is not the right length!", oldColumnNames[i].length, newColumnNames[i].length );
167             for ( int j = 0; j < oldColumnNames[i].length; j++ ) {
168                 assertEquals( "Column name [" + i + "," + j + "]", oldColumnNames[i][j], newColumnNames[i][j] );
169             }
170         }*/

171     }
172
173     private void checkReturnedTypes(QueryTranslator oldQueryTranslator, QueryTranslator newQueryTranslator) {
174         // Check the returned types for a regression.
175
Type[] oldReturnTypes = oldQueryTranslator.getReturnTypes();
176         Type[] returnTypes = newQueryTranslator.getReturnTypes();
177         assertEquals( "Return types array is not the right length!", oldReturnTypes.length, returnTypes.length );
178         for ( int i = 0; i < returnTypes.length; i++ ) {
179             assertNotNull( returnTypes[i] );
180             assertNotNull( oldReturnTypes[i] );
181             assertEquals( "Returned types did not match!", oldReturnTypes[i].getReturnedClass(), returnTypes[i].getReturnedClass() );
182             System.out.println("returnedType[" + i + "] = " + returnTypes[i] + " oldReturnTypes[" + i + "] = " + oldReturnTypes[i]);
183         }
184     }
185
186     private void checkQuerySpaces(QueryTranslator oldQueryTranslator, QueryTranslator newQueryTranslator) {
187         // Check the query spaces for a regression.
188
Set JavaDoc oldQuerySpaces = oldQueryTranslator.getQuerySpaces();
189         Set JavaDoc querySpaces = newQueryTranslator.getQuerySpaces();
190         assertEquals( "Query spaces is not the right size!", oldQuerySpaces.size(), querySpaces.size() );
191         for ( Iterator JavaDoc iterator = oldQuerySpaces.iterator(); iterator.hasNext(); ) {
192             Object JavaDoc o = iterator.next();
193             assertTrue( "New query space does not contain " + o + "!", querySpaces.contains( o ) );
194         }
195     }
196
197     protected Exception JavaDoc compileBadHql(String JavaDoc hql, boolean scalar) {
198         QueryTranslator newQueryTranslator;
199         Map JavaDoc replacements = null;
200         Exception JavaDoc newException = null;
201         SessionFactoryImplementor factory = getSessionFactoryImplementor();
202         try {
203             QueryTranslatorFactory ast = new ASTQueryTranslatorFactory();
204             newQueryTranslator = ast.createQueryTranslator( hql, Collections.EMPTY_MAP, factory );
205             newQueryTranslator.compile( replacements, scalar );
206         }
207         catch ( QueryException e ) {
208             newException = e;
209         }
210         catch ( MappingException e ) {
211             newException = e;
212         }
213         assertNotNull( "Expected exception from compilation of '" + hql + "'!", newException );
214         return newException;
215     }
216
217     private void checkSql(QueryTranslator oldQueryTranslator, QueryTranslator newQueryTranslator, String JavaDoc hql, boolean scalar, String JavaDoc sql) {
218
219         String JavaDoc oldsql = oldQueryTranslator.getSQLString();
220         String JavaDoc newsql = newQueryTranslator.getSQLString();
221         System.out.println( "HQL : " + ASTPrinter.escapeMultibyteChars(hql) );
222         System.out.println( "OLD SQL: " + ASTPrinter.escapeMultibyteChars(oldsql) );
223         System.out.println( "NEW SQL: " + ASTPrinter.escapeMultibyteChars(newsql) );
224         if ( sql == null ) {
225             // Check the generated SQL. ASTPrinter.escapeMultibyteChars(
226
assertSQLEquals( "SQL is not the same as the old SQL (scalar=" + scalar + ")", oldsql, newsql );
227         }
228         else {
229             assertSQLEquals( "SQL is not the same as the expected SQL (scalar=" + scalar + ")", sql, newsql );
230         }
231     }
232
233     private void assertSQLEquals(String JavaDoc message, String JavaDoc oldsql, String JavaDoc newsql) {
234         Map JavaDoc oldMap = getTokens(oldsql);
235         Map JavaDoc newMap = getTokens(newsql);
236         if ( !oldMap.equals(newMap) ) {
237             assertEquals(message, oldsql, newsql);
238         }
239         
240         //String oldsqlStripped = stripExtraSpaces( oldsql );
241
//String newsqlStripped = stripExtraSpaces( newsql );
242
//assertEquals( message, oldsqlStripped, newsqlStripped );
243
}
244
245     
246     private Map JavaDoc getTokens(String JavaDoc sql) {
247         Map JavaDoc result = new TreeMap JavaDoc();
248         if (sql==null) return result;
249         result.put( "=", new Integer JavaDoc( StringHelper.countUnquoted(sql, '=') ) );
250         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc( sql, "(),= " );
251         while ( tokenizer.hasMoreTokens() ) {
252             String JavaDoc fragment = tokenizer.nextToken();
253             /*if ( "on".equals(fragment) ) fragment = "and";
254             if ( "join".equals(fragment) || "inner".equals(fragment) ) continue;*/

255             Integer JavaDoc count = (Integer JavaDoc) result.get(fragment);
256             if ( count==null ) {
257                 count = new Integer JavaDoc(1);
258             }
259             else {
260                 count = new Integer JavaDoc( count.intValue() + 1 );
261             }
262             result.put(fragment, count);
263         }
264         return result;
265     }
266     
267     private String JavaDoc stripExtraSpaces(String JavaDoc string) {
268         if ( string == null ) {
269             return null;
270         }
271
272         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc( string.length() );
273         char[] chars = string.toCharArray();
274         int length = chars.length;
275         boolean wasSpace = false;
276         for ( int i = 0; i < length; i++ ) {
277             boolean isSpace = chars[i] == ' ';
278             if ( wasSpace && isSpace ) {
279                 continue;
280             }
281             else {
282                 buffer.append( chars[i] );
283             }
284
285             wasSpace = isSpace;
286         }
287 // StringTokenizer tokenizer = new StringTokenizer( string.trim(), " " );
288
// while ( tokenizer.hasMoreTokens() ) {
289
// final String fragment = tokenizer.nextToken();
290
// buffer.append( fragment );
291
// buffer.append( " " );
292
// }
293
//
294
return buffer.toString();
295     }
296
297     private void checkSqlByResultSet(
298             QueryTranslator oldQueryTranslator,
299             QueryTranslator newQueryTranslator,
300             Object JavaDoc[] binds
301     ) {
302         String JavaDoc oldsql = oldQueryTranslator.getSQLString();
303         String JavaDoc newsql = newQueryTranslator.getSQLString();
304
305         Session session = openSession();
306         Connection JavaDoc connection = session.connection();
307
308         PreparedStatement JavaDoc oldps = null;
309         PreparedStatement JavaDoc newps = null;
310         ResultSet JavaDoc oldrs = null;
311         ResultSet JavaDoc newrs = null;
312
313         try {
314             try {
315                 oldps = connection.prepareStatement( oldsql );
316             }
317             catch( Throwable JavaDoc t ) {
318                 fail( "Unable to prepare sql generated by old parser : " + t );
319             }
320             try {
321                 newps = connection.prepareStatement( newsql );
322             }
323             catch( Throwable JavaDoc t ) {
324                 fail( "Unable to prepare sql generated by new parser : " + t );
325             }
326
327             checkBinds(oldps, newps, binds);
328
329             try {
330                 oldrs = executeQuery( oldps, binds );
331             }
332             catch( Throwable JavaDoc t ) {
333                 fail( "Unable to execute sql generated by old parser : " + t );
334             }
335
336             try {
337                 newrs = executeQuery( newps, binds );
338             }
339             catch( Throwable JavaDoc t ) {
340                 fail( "Unable to execute sql generated by new parser : " + t );
341             }
342
343             checkResults( oldrs, newrs );
344         }
345         finally {
346             // make *sure* the sql resources get cleaned up
347
release(oldrs);
348             release(newrs);
349             release(oldps);
350             release(newps);
351             release(session);
352         }
353     }
354
355     private void checkBinds(PreparedStatement JavaDoc oldps, PreparedStatement JavaDoc newps, Object JavaDoc[] binds) {
356         // Make sure the binds "feel" ok
357
try {
358             ParameterMetaData JavaDoc oldBindMetaData = oldps.getParameterMetaData();
359             ParameterMetaData JavaDoc newBindMetaData = newps.getParameterMetaData();
360
361             assertEquals( "Different bind parameter count", oldBindMetaData.getParameterCount(), newBindMetaData.getParameterCount() );
362             assertEquals( "Incorrect number of binds passed in", oldBindMetaData.getParameterCount(), binds == null ? 0 : binds.length );
363
364             for ( int i = 0, max = oldBindMetaData.getParameterCount(); i < max; i++ ) {
365                 assertEquals( "Different bind types", oldBindMetaData.getParameterType(i), newBindMetaData.getParameterType(i) );
366             }
367         }
368         catch( Throwable JavaDoc t ) {
369             fail( "SQLException comparing binds : " + t );
370         }
371     }
372
373     private ResultSet JavaDoc executeQuery(PreparedStatement JavaDoc ps, Object JavaDoc[] binds) throws SQLException JavaDoc {
374         if ( binds != null ) {
375             for ( int i = 0, max = binds.length; i < max; i++ ) {
376                 ps.setObject( i, binds[i] );
377             }
378         }
379
380         return ps.executeQuery();
381     }
382
383     private void checkResults(ResultSet JavaDoc oldrs, ResultSet JavaDoc newrs) {
384         ResultSetMetaData JavaDoc oldmeta = null;
385         ResultSetMetaData JavaDoc newmeta = null;
386         int colCount = 0;
387         Type[] types = null;
388
389         // first compare the metadata from the two results
390
try {
391             oldmeta = oldrs.getMetaData();
392             newmeta = newrs.getMetaData();
393             assertEquals( "Different column counts", oldmeta.getColumnCount(), newmeta.getColumnCount() );
394
395             colCount = oldmeta.getColumnCount();
396             types = new Type[colCount];
397
398             for ( int i = 1, max = colCount; i < max; i++ ) {
399                 assertEquals( "Column names were different", oldmeta.getColumnName(i), newmeta.getColumnName(i) );
400                 assertEquals( "Column types were different", oldmeta.getColumnType(i), newmeta.getColumnType(i) );
401                 assertEquals( "Java types were different", oldmeta.getColumnClassName(i), newmeta.getColumnClassName(i) );
402                 types[i] = TypeFactory.basic( oldmeta.getColumnClassName(i) );
403             }
404         }
405         catch( Throwable JavaDoc t ) {
406             fail( "Error comparing result set metadata" );
407         }
408
409         // Then compare the actual results
410
try {
411             while ( oldrs.next() & newrs.next() ) {
412                 for ( int i = 1; i < colCount; i++ ) {
413                     Object JavaDoc oldval = oldrs.getObject(i);
414                     if ( oldrs.wasNull() ) oldval = null;
415                     Object JavaDoc newval = newrs.getObject(i);
416                     if ( newrs.wasNull() ) newval = null;
417                     checkLogicalEquality( oldval, newval, types[i] );
418                 }
419             }
420
421             // for "better reporting" purposes, make sure both result sets are fully exhausted
422
while ( oldrs.next() );
423             while ( newrs.next() );
424
425             assertEquals( "Different row counts", oldrs.getRow(), newrs.getRow() );
426         }
427         catch( Throwable JavaDoc t ) {
428             fail( "Error comparing result set structure" );
429         }
430     }
431
432     private void checkLogicalEquality(Object JavaDoc oldval, Object JavaDoc newval, Type type) {
433         if ( oldval == null && newval == null ) {
434             // two nulls are logically equivalent here...
435
return;
436         }
437         else {
438             assertTrue( "Different result values", type.isEqual(oldval, newval, EntityMode.POJO) );
439         }
440     }
441
442     private void release(PreparedStatement JavaDoc ps) {
443         if ( ps != null ) {
444             try {
445                 ps.close();
446             }
447             catch( Throwable JavaDoc t ) {}
448         }
449     }
450
451     private void release(ResultSet JavaDoc rs) {
452         if ( rs != null ) {
453             try {
454                 rs.close();
455             }
456             catch( Throwable JavaDoc t ) {}
457         }
458     }
459
460     private void release(Session session) {
461         if ( session != null ) {
462             try {
463                 session.close();
464             }
465             catch( Throwable JavaDoc t ) {}
466         }
467     }
468
469     protected String JavaDoc[] getMappings() {
470         return new String JavaDoc[]{
471             "hql/Animal.hbm.xml",
472             "hql/EntityWithCrazyCompositeKey.hbm.xml",
473             "batchfetch/ProductLine.hbm.xml",
474             "cid/Customer.hbm.xml",
475             "cid/Order.hbm.xml",
476             "cid/LineItem.hbm.xml",
477             "cid/Product.hbm.xml",
478             "legacy/Baz.hbm.xml",
479             "legacy/Category.hbm.xml",
480             "legacy/Commento.hbm.xml",
481             "legacy/Container.hbm.xml",
482             "legacy/Custom.hbm.xml",
483             "legacy/Eye.hbm.xml",
484             "legacy/Fee.hbm.xml",
485             "legacy/FooBar.hbm.xml",
486             "legacy/Fum.hbm.xml",
487             "legacy/Glarch.hbm.xml",
488             "legacy/Holder.hbm.xml",
489             "legacy/Many.hbm.xml",
490             "legacy/Marelo.hbm.xml",
491             "legacy/MasterDetail.hbm.xml",
492             "legacy/Middle.hbm.xml",
493             "legacy/Multi.hbm.xml",
494             "legacy/Nameable.hbm.xml",
495             "legacy/One.hbm.xml",
496             "legacy/Qux.hbm.xml",
497             "legacy/Simple.hbm.xml",
498             "legacy/SingleSeveral.hbm.xml",
499             "legacy/WZ.hbm.xml",
500             "legacy/UpDown.hbm.xml",
501             "compositeelement/Parent.hbm.xml",
502             "onetoone/joined/Person.hbm.xml",
503             "hql/CrazyIdFieldNames.hbm.xml"
504         };
505     }
506
507     protected boolean recreateSchema() {
508         // we do not need to create the schema for these parser tests
509
return false;
510     }
511 }
512
Popular Tags