Update of /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/hql In directory sc8-pr-cvs1:/tmp/cvs-serv3046 Modified Files: PathExpressionParser.java QueryTranslator.java SelectParser.java WhereParser.java Log Message: fixed bugs querying a many-to-one association to a <joined-subclass> Index: PathExpressionParser.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/hql/PathExpressionParser.java,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** PathExpressionParser.java 6 Apr 2003 02:28:57 -0000 1.17 --- PathExpressionParser.java 3 May 2003 06:58:30 -0000 1.18 *************** *** 11,14 **** --- 11,15 ---- import net.sf.hibernate.persister.Queryable; import net.sf.hibernate.sql.JoinFragment; + import net.sf.hibernate.sql.QueryJoinFragment; import net.sf.hibernate.type.EntityType; import net.sf.hibernate.type.PersistentCollectionType; *************** *** 26,29 **** --- 27,35 ---- //ways in which path expressions can occur + //We should actually rework this class to not implement Parser + //and just process path expressions in the most convenient way. + + //The class is now way to complex! + public static final String ENTITY_ID = "id"; public static final String ENTITY_CLASS = "class"; *************** *** 39,43 **** protected String currentName; protected String currentProperty; ! protected JoinFragment join; protected String[] columns; protected String[] collectionElementColumns; --- 45,49 ---- protected String currentName; protected String currentProperty; ! protected QueryJoinFragment join; protected String[] columns; protected String[] collectionElementColumns; *************** *** 53,56 **** --- 59,63 ---- private boolean continuation; private int joinType = JoinFragment.INNER_JOIN; //default mode + private boolean endsWithCollectionProperty = false; void setJoinType(int joinType) { *************** *** 59,64 **** private void addJoin(String table, String name, String[] rhsCols, QueryTranslator q) throws QueryException { String[] lhsCols = currentColumns(q); ! join.addJoin(table, name, lhsCols, rhsCols, joinType); } --- 66,74 ---- private void addJoin(String table, String name, String[] rhsCols, QueryTranslator q) throws QueryException { + addJoin(table, name, name, rhsCols, q); + } + private void addJoin(String table, String name, String concreteAlias, String[] rhsCols, QueryTranslator q) throws QueryException { String[] lhsCols = currentColumns(q); ! join.addJoin(table, name, concreteAlias, lhsCols, rhsCols, joinType); } *************** *** 163,176 **** collectionRole = ( (PersistentCollectionType) propertyType ).getRole(); ! CollectionPersister p = q.getCollectionPersister(collectionRole); ! String[] colNames = p.getKeyColumnNames(); String name= q.createNameForCollection(collectionRole); ! addJoin( p.getQualifiedTableName(), name, colNames, q ); ! if ( p.hasWhere() ) join.addCondition( p.getSQLWhereString(name) ); ! doCollectionProperty(token, p, name); collectionName = name; ! collectionTable = p.getQualifiedTableName(); currentName=null; currentProperty=null; --- 173,200 ---- collectionRole = ( (PersistentCollectionType) propertyType ).getRole(); ! CollectionPersister collPersister = q.getCollectionPersister(collectionRole); ! String[] colNames = collPersister.getKeyColumnNames(); String name= q.createNameForCollection(collectionRole); ! String tableName; ! String concreteAlias; ! if ( collPersister.isOneToMany() && !endsWithCollectionProperty ) { ! Queryable persister = q.getPersister( ( (EntityType) collPersister.getElementType() ).getPersistentClass() ); ! tableName = persister.getTableName(); ! concreteAlias = persister.getConcreteClassAlias(name); ! if ( joinType!=JoinFragment.INNER_JOIN && !name.equals(concreteAlias) ) ! throw new QueryException("outer and full join to collection of a subclass not currently supported by this mapping strategy: " +path); ! } ! else { ! tableName = collPersister.getQualifiedTableName(); ! concreteAlias=name; ! } ! ! addJoin(tableName, name, concreteAlias, colNames, q); ! if ( collPersister.hasWhere() ) join.addCondition( collPersister.getSQLWhereString(name) ); ! doCollectionProperty(token, collPersister, name); collectionName = name; ! collectionTable = collPersister.getQualifiedTableName(); currentName=null; currentProperty=null; *************** *** 253,257 **** --- 277,283 ---- public void end(QueryTranslator q) throws QueryException { + endsWithCollectionProperty = false; ignoreInitialJoin = false; + if ( isCollectionValued() ) { columns = collectionElementColumns; *************** *** 270,292 **** //special case; expecting: [index] ! CollectionPersister memberPersister = q.getCollectionPersister(collectionRole); ! if ( !memberPersister.hasIndex() ) throw new QueryException("unindexed collection before []: " + path); ! String[] indexCols = memberPersister.getIndexColumnNames(); if ( indexCols.length!=1 ) throw new QueryException("composite-index appears in []: " + path); ! String[] keyCols = memberPersister.getKeyColumnNames(); if (!continuation) { ! addJoin( memberPersister.getQualifiedTableName(), collectionName, keyCols, q ); } ! join.addCondition(collectionName, indexCols, " = "); ! String[] eltCols = memberPersister.getElementColumnNames(); //if ( eltCols.length!=1 ) throw new QueryException("composite-id collection element []"); CollectionElement elem = new CollectionElement(); elem.elementColumns = StringHelper.prefix( eltCols, collectionName + StringHelper.DOT ); ! elem.type = memberPersister.getElementType(); ! elem.isOneToMany = memberPersister.isOneToMany(); elem.alias = collectionName; elem.join = join; --- 296,334 ---- //special case; expecting: [index] ! CollectionPersister collPersister = q.getCollectionPersister(collectionRole); ! if ( !collPersister.hasIndex() ) throw new QueryException("unindexed collection before []: " + path); ! String[] indexCols = collPersister.getIndexColumnNames(); if ( indexCols.length!=1 ) throw new QueryException("composite-index appears in []: " + path); ! String[] keyCols = collPersister.getKeyColumnNames(); + String concreteAlias; + JoinFragment ojf = q.createJoinFragment(); + if ( collPersister.isOneToMany() ) { + Queryable persister = q.getPersister( ( (EntityType) collPersister.getElementType() ).getPersistentClass() ); + ojf.addCrossJoin( persister.getTableName(), collectionName ); + ojf.addJoins( + persister.fromJoinFragment(collectionName, true, false), + persister.whereJoinFragment(collectionName, true, false) + ); + concreteAlias = persister.getConcreteClassAlias(collectionName); + } + else { + ojf.addCrossJoin( collPersister.getQualifiedTableName(), collectionName ); + concreteAlias = collectionName; + } + if (!continuation) { ! addJoin( collPersister.getQualifiedTableName(), concreteAlias, keyCols, q ); } ! join.addCondition(concreteAlias, indexCols, " = "); ! String[] eltCols = collPersister.getElementColumnNames(); //if ( eltCols.length!=1 ) throw new QueryException("composite-id collection element []"); CollectionElement elem = new CollectionElement(); elem.elementColumns = StringHelper.prefix( eltCols, collectionName + StringHelper.DOT ); ! elem.type = collPersister.getElementType(); ! elem.isOneToMany = collPersister.isOneToMany(); elem.alias = collectionName; elem.join = join; *************** *** 295,300 **** q.addCollection(collectionName, collectionRole); - JoinFragment ojf = q.createJoinFragment(); - ojf.addCrossJoin( memberPersister.getQualifiedTableName(), collectionName ); q.addJoin(collectionName, ojf); } --- 337,340 ---- *************** *** 308,311 **** --- 348,352 ---- //important!! continuation=false; + } *************** *** 469,472 **** --- 510,527 ---- throw new QueryException("expecting 'elements' or 'indices' after: " + path); } + } + + /** + * Very ugly hack to allow collection paths to be processed correctly + * for normalized mappings + */ + public final void setPath(String path) { + endsWithCollectionProperty = path.endsWith(COLLECTION_ELEMENTS) || + path.endsWith(COLLECTION_INDICES) || + path.endsWith(COLLECTION_SIZE) || + path.endsWith(COLLECTION_MAX_INDEX) || + path.endsWith(COLLECTION_MAX_ELEMENT) || + path.endsWith(COLLECTION_MIN_INDEX) || + path.endsWith(COLLECTION_MIN_ELEMENT); } Index: QueryTranslator.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/hql/QueryTranslator.java,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** QueryTranslator.java 25 Apr 2003 05:56:33 -0000 1.25 --- QueryTranslator.java 3 May 2003 06:58:30 -0000 1.26 *************** *** 38,42 **** import net.sf.hibernate.type.Type; import net.sf.hibernate.util.ArrayHelper; - import net.sf.hibernate.util.JDBCExceptionReporter; import net.sf.hibernate.util.ReflectHelper; import net.sf.hibernate.util.StringHelper; --- 38,41 ---- *************** *** 112,116 **** * times. Subsequent invocations are no-ops. */ ! public synchronized void compile(SessionFactoryImplementor factory, String queryString, Map replacements, boolean scalar) throws QueryException, MappingException { if (!compiled) { this.factory = factory; --- 111,116 ---- * times. Subsequent invocations are no-ops. */ ! public synchronized void compile(SessionFactoryImplementor factory, String queryString, Map replacements, boolean scalar) ! throws QueryException, MappingException { if (!compiled) { this.factory = factory; *************** *** 659,665 **** JoinFragment join = createJoinFragment(); if ( persister.isOneToMany() ) { ! join.addCrossJoin( persister.getQualifiedTableName(), elementName ); ! join.addCondition(elementName, keyColumnNames, " = ?"); ! if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(elementName) ); } else { //many-to-many --- 659,667 ---- JoinFragment join = createJoinFragment(); if ( persister.isOneToMany() ) { ! Queryable classPersister = getPersister( ( (EntityType) persister.getElementType() ).getPersistentClass() ); ! String concreteAlias = classPersister.getConcreteClassAlias(elementName); ! join.addCrossJoin( classPersister.getTableName(), elementName ); ! join.addCondition(concreteAlias, keyColumnNames, " = ?"); ! if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(concreteAlias) ); } else { //many-to-many *************** *** 701,705 **** } ! protected void bindNamedParameters(PreparedStatement ps, Map namedParams, int start, SessionImplementor session) throws SQLException, HibernateException { if (namedParams!=null) { Iterator iter = namedParams.entrySet().iterator(); --- 703,707 ---- } ! protected int bindNamedParameters(PreparedStatement ps, Map namedParams, int start, SessionImplementor session) throws SQLException, HibernateException { if (namedParams!=null) { Iterator iter = namedParams.entrySet().iterator(); *************** *** 713,716 **** --- 715,722 ---- } } + return namedParams.size(); + } + else { + return 0; } } *************** *** 719,733 **** PreparedStatement st = prepareQueryStatement( getSQLString(), values, types, namedParams, selection, false, session ); ! try { ! setMaxRows(st, selection); ! ResultSet rs = st.executeQuery(); ! advance(rs, selection, session); ! return new IteratorImpl( rs, session, getReturnTypes(), getScalarColumnNames() ); ! } ! catch (SQLException sqle) { ! JDBCExceptionReporter.logExceptions(sqle); ! closePreparedStatement(st, selection, session); ! throw sqle; ! } } --- 725,731 ---- PreparedStatement st = prepareQueryStatement( getSQLString(), values, types, namedParams, selection, false, session ); ! ResultSet rs = getResultSet(st, selection, session); ! return new IteratorImpl( rs, session, getReturnTypes(), getScalarColumnNames() ); ! } *************** *** 735,749 **** PreparedStatement st = prepareQueryStatement( getSQLString(), values, types, namedParams, selection, true, session ); ! try { ! setMaxRows(st, selection); ! ResultSet rs = st.executeQuery(); ! advance(rs, selection, session); ! return new ScrollableResultsImpl( rs, session, getReturnTypes() ); ! } ! catch (SQLException sqle) { ! JDBCExceptionReporter.logExceptions(sqle); ! closePreparedStatement(st, selection, session); ! throw sqle; ! } } --- 733,739 ---- PreparedStatement st = prepareQueryStatement( getSQLString(), values, types, namedParams, selection, true, session ); ! ResultSet rs = getResultSet(st, selection, session); ! return new ScrollableResultsImpl( rs, session, getReturnTypes() ); ! } Index: SelectParser.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/hql/SelectParser.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** SelectParser.java 8 Apr 2003 09:49:29 -0000 1.10 --- SelectParser.java 3 May 2003 06:58:30 -0000 1.11 *************** *** 121,124 **** --- 121,125 ---- else if (aggregate) { if (!ready) throw new QueryException("( expected after aggregate function in SELECT"); + aggregatePathExpressionParser.setPath(token); ParserHelper.parse(aggregatePathExpressionParser, q.unalias(token), ParserHelper.PATH_SEPARATORS, q); *************** *** 135,139 **** else { if (!ready) throw new QueryException(", expected in SELECT"); ! ParserHelper.parse(pathExpressionParser, q.unalias(token), ParserHelper.PATH_SEPARATORS, q); if ( pathExpressionParser.isCollectionValued() ) { --- 136,140 ---- else { if (!ready) throw new QueryException(", expected in SELECT"); ! pathExpressionParser.setPath(token); ParserHelper.parse(pathExpressionParser, q.unalias(token), ParserHelper.PATH_SEPARATORS, q); if ( pathExpressionParser.isCollectionValued() ) { Index: WhereParser.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/hql/WhereParser.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** WhereParser.java 3 Apr 2003 12:34:25 -0000 1.12 --- WhereParser.java 3 May 2003 06:58:30 -0000 1.13 *************** *** 357,360 **** --- 357,362 ---- preprocess(token, q); + pathExpressionParser.setPath(token); + StringTokenizer tokens = new StringTokenizer(token, ".", true); pathExpressionParser.start(q); |