Update of /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/loader In directory sc8-pr-cvs1:/tmp/cvs-serv2323/sf/hibernate/loader Modified Files: CollectionLoader.java EntityLoader.java Loader.java OneToManyLoader.java OuterJoinLoader.java SimpleEntityLoader.java Log Message: major refactoring to create SQL Generation layer more efficient queries against normalized mappings Index: CollectionLoader.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/loader/CollectionLoader.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** CollectionLoader.java 15 Jan 2003 12:49:01 -0000 1.5 --- CollectionLoader.java 20 Jan 2003 12:48:12 -0000 1.6 *************** *** 13,17 **** --- 13,21 ---- import net.sf.hibernate.engine.SessionImplementor; import net.sf.hibernate.persister.Loadable; + import net.sf.hibernate.sql.ConditionFragment; + import net.sf.hibernate.sql.OuterJoinFragment; + import net.sf.hibernate.sql.Select; import net.sf.hibernate.type.Type; + import net.sf.hibernate.util.StringHelper; /** *************** *** 38,60 **** int joins=associations.size(); suffixes = new String[joins]; ! for ( int i=0; i<joins; i++ ) suffixes[i] = (joins==1) ? "" : Integer.toString(i); ! sql = sqlSelect( ! // SELECT CLAUSE ! selectCollectionString(persister, alias) + ! ( joins==0 ? "" : ", " + selectString(associations) ), ! // FROM CLAUSE ! persister.getQualifiedTableName() + ' ' + alias, ! // OUTER JOINS (Insertion Point 1) ! outerJoinGenerator.outerJoinStringAfterFrom(associations), ! // WHERE CLAUSE ! whereString( persister.getKeyColumnNames(), alias ), ! // OUTER JOINS (Insertion Point 2) ! outerJoinGenerator.outerJoinStringAfterWhere(associations), ! // ORDER BY CLAUSE ! ( persister.hasOrdering() ) ? ! persister.getSQLOrderByString(alias) : ! null ! ); classPersisters = new Loadable[joins]; --- 42,64 ---- int joins=associations.size(); suffixes = new String[joins]; ! for ( int i=0; i<joins; i++ ) suffixes[i] = (joins==1) ? StringHelper.EMPTY_STRING : Integer.toString(i); ! OuterJoinFragment ojf = outerJoins(associations); ! Select select = new Select() ! .setSelectClause( ! persister.selectClauseFragment(alias) + ( joins==0 ? StringHelper.EMPTY_STRING : ", " + selectString(associations) ) ! ) ! .setFromClause( persister.getQualifiedTableName(), alias ) ! .setWhereClause( ! new ConditionFragment().setTableAlias(alias) ! .setCondition( persister.getKeyColumnNames(), "?" ) ! .toFragmentString() ! ) ! .setOuterJoins( ! ojf.toFromFragmentString(), ! ojf.toWhereFragmentString() ! ); ! if ( persister.hasOrdering() ) select.setOrderByClause( persister.getSQLOrderByString(alias) ); ! sql = select.toStatementString(); classPersisters = new Loadable[joins]; Index: EntityLoader.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/loader/EntityLoader.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** EntityLoader.java 18 Jan 2003 09:03:54 -0000 1.6 --- EntityLoader.java 20 Jan 2003 12:48:12 -0000 1.7 *************** *** 12,16 **** --- 12,20 ---- import net.sf.hibernate.persister.ClassPersister; import net.sf.hibernate.persister.Loadable; + import net.sf.hibernate.sql.ConditionFragment; + import net.sf.hibernate.sql.OuterJoinFragment; + import net.sf.hibernate.sql.Select; import net.sf.hibernate.type.Type; + import net.sf.hibernate.util.StringHelper; /** *************** *** 35,54 **** int joins=associations.size(); suffixes = new String[joins+1]; ! for ( int i=0; i<=joins; i++ ) suffixes[i] = (joins==0) ? "" : Integer.toString(i); ! sql = sqlSelect( ! //SELECT CLAUSE ! ( joins==0 ? "" : selectString(associations) + ", " ) + ! selectString( persister, alias, suffixes[joins] ), ! // FROM CLAUSE ! persister.fromClauseFragment(alias, true), ! // OUTER JOINS (Insertion Point 1) ! outerJoinGenerator.outerJoinStringAfterFrom(associations), ! // WHERE CLAUSE ! whereString( persister.getIdentifierColumnNames(), alias ), ! // OUTER JOINS (Insertion Point 2) ! outerJoinGenerator.outerJoinStringAfterWhere(associations) + ! persister.outerJoinsAfterWhere(alias, true) ! ); classPersisters = new Loadable[joins+1]; --- 39,61 ---- int joins=associations.size(); suffixes = new String[joins+1]; ! for ( int i=0; i<=joins; i++ ) suffixes[i] = (joins==0) ? StringHelper.EMPTY_STRING : Integer.toString(i); ! OuterJoinFragment ojf = outerJoins(associations); ! sql = new Select() ! .setSelectClause( ! ( joins==0 ? StringHelper.EMPTY_STRING : selectString(associations) + ", " ) + ! selectString( persister, alias, suffixes[joins] ) ! ) ! .setFromClause( persister.fromClauseFragment(alias, true, true) ) ! .setWhereClause( ! new ConditionFragment().setTableAlias(alias) ! .setCondition( persister.getIdentifierColumnNames(), "?" ) ! .toFragmentString() ! ) ! .setOuterJoins( ! ojf.toFromFragmentString(), ! ojf.toWhereFragmentString() ! ) ! .toStatementString(); classPersisters = new Loadable[joins+1]; Index: Loader.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/loader/Loader.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Loader.java 18 Jan 2003 09:03:54 -0000 1.6 --- Loader.java 20 Jan 2003 12:48:12 -0000 1.7 *************** *** 485,511 **** } - /** - * Construct an SQL <tt>SELECT</tt> statement from the given clauses - */ - protected static final String sqlSelect(String selectClause, String fromClause, String outerJoinsAfterFrom, String whereClause, String outerJoinsAfterWhere) { - return sqlSelect(selectClause, fromClause, outerJoinsAfterFrom, whereClause, outerJoinsAfterWhere, null); - } - - /** - * Construct an SQL <tt>SELECT</tt> statement from the given clauses - */ - protected static final String sqlSelect(String selectClause, String fromClause, String outerJoinsAfterFrom, String whereClause, String outerJoinsAfterWhere, String orderByClause) { - StringBuffer buf = new StringBuffer( - selectClause.length() + fromClause.length() + outerJoinsAfterFrom.length() + whereClause.length() + outerJoinsAfterWhere.length() + 20 - ); - buf.append("SELECT ").append(selectClause) - .append(" FROM ").append(fromClause) - .append(outerJoinsAfterFrom) - .append(" WHERE ").append(whereClause) - .append(outerJoinsAfterWhere); - if (orderByClause!=null) buf.append(" ORDER BY ").append(orderByClause); - return buf.toString(); - } - } --- 485,488 ---- Index: OneToManyLoader.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/loader/OneToManyLoader.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** OneToManyLoader.java 15 Jan 2003 12:49:01 -0000 1.5 --- OneToManyLoader.java 20 Jan 2003 12:48:13 -0000 1.6 *************** *** 13,18 **** --- 13,22 ---- import net.sf.hibernate.engine.SessionImplementor; import net.sf.hibernate.persister.Loadable; + import net.sf.hibernate.sql.ConditionFragment; + import net.sf.hibernate.sql.OuterJoinFragment; + import net.sf.hibernate.sql.Select; import net.sf.hibernate.type.EntityType; import net.sf.hibernate.type.Type; + import net.sf.hibernate.util.StringHelper; /** *************** *** 46,71 **** int joins=associations.size(); suffixes = new String[joins+1]; ! for ( int i=0; i<=joins; i++ ) suffixes[i] = (joins==0) ? "" : Integer.toString(i); ! sql = sqlSelect( ! // SELECT CLAUSE ! selectCollectionString(collPersister, collAlias) + ! ( joins==0 ? "" : ", " + selectString(associations) ) ! + ", " + ! selectString( persister, alias, suffixes[joins] ), ! // FROM CLAUSE ! persister.fromClauseFragment(alias, true), ! // OUTER JOINS (Insertion Point 1) ! outerJoinGenerator.outerJoinStringAfterFrom(associations), ! // WHERE CLAUSE ! whereString( collPersister.getKeyColumnNames(), collAlias ), ! // OUTER JOINS (Insertion Point 2) ! outerJoinGenerator.outerJoinStringAfterWhere(associations) + ! persister.outerJoinsAfterWhere(alias, true), ! // ORDER BY CLAUSE ! collPersister.hasOrdering() ? ! collPersister.getSQLOrderByString(collAlias) : ! null ! ); classPersisters = new Loadable[joins+1]; --- 50,75 ---- int joins=associations.size(); suffixes = new String[joins+1]; ! for ( int i=0; i<=joins; i++ ) suffixes[i] = (joins==0) ? StringHelper.EMPTY_STRING : Integer.toString(i); ! OuterJoinFragment ojf = outerJoins(associations); ! Select select = new Select() ! .setSelectClause( ! collPersister.selectClauseFragment(collAlias) + ! ( joins==0 ? StringHelper.EMPTY_STRING : ", " + selectString(associations) ) + ! ", " + ! selectString( persister, alias, suffixes[joins] ) ! ) ! .setFromClause( persister.fromClauseFragment(alias, true, true) ) ! .setWhereClause( ! new ConditionFragment().setTableAlias(collAlias) ! .setCondition( collPersister.getKeyColumnNames(), "?" ) ! .toFragmentString() ! ) ! .setOuterJoins( ! ojf.toFromFragmentString(), ! ojf.toWhereFragmentString() ! ); ! if ( collPersister.hasOrdering() ) select.setOrderByClause( collPersister.getSQLOrderByString(collAlias) ); ! sql = select.toStatementString(); classPersisters = new Loadable[joins+1]; Index: OuterJoinLoader.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/loader/OuterJoinLoader.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** OuterJoinLoader.java 18 Jan 2003 09:57:36 -0000 1.8 --- OuterJoinLoader.java 20 Jan 2003 12:48:13 -0000 1.9 *************** *** 4,7 **** --- 4,8 ---- import java.util.ArrayList; import java.util.HashSet; + import java.util.Iterator; import java.util.List; import java.util.Set; *************** *** 13,17 **** import net.sf.hibernate.persister.ClassPersister; import net.sf.hibernate.persister.Loadable; ! import net.sf.hibernate.persister.MultiTableEntityPersister; import net.sf.hibernate.type.AbstractComponentType; import net.sf.hibernate.type.EntityType; --- 14,19 ---- import net.sf.hibernate.persister.ClassPersister; import net.sf.hibernate.persister.Loadable; ! import net.sf.hibernate.persister.NormalizedEntityPersister; ! import net.sf.hibernate.sql.OuterJoinFragment; import net.sf.hibernate.type.AbstractComponentType; import net.sf.hibernate.type.EntityType; *************** *** 39,50 **** protected String sql; protected String[] suffixes; ! protected final OuterJoinGenerator outerJoinGenerator; public OuterJoinLoader(Dialect dialect) { ! outerJoinGenerator = dialect.getOuterJoinGenerator(); } public static final class OuterJoinableAssociation { - //Object persister; // a class or collection persister! public Loadable subpersister; public String[] foreignKeyColumns; // belong to persister --- 41,51 ---- protected String sql; protected String[] suffixes; ! private Dialect dialect; public OuterJoinLoader(Dialect dialect) { ! this.dialect=dialect; } public static final class OuterJoinableAssociation { public Loadable subpersister; public String[] foreignKeyColumns; // belong to persister *************** *** 75,79 **** if ( autoEager( persister.enableJoinedFetch(), etype, session ) ) { // fetch many-to-many by outerjoin depending value of outer-join in mapping ! String[] columns = StringHelper.prefix( persister.getElementColumnNames(), alias + '.' ); walkTree(etype, columns, persister, associations, new HashSet(), session); } --- 76,80 ---- if ( autoEager( persister.enableJoinedFetch(), etype, session ) ) { // fetch many-to-many by outerjoin depending value of outer-join in mapping ! String[] columns = StringHelper.prefix( persister.getElementColumnNames(), alias + StringHelper.DOT ); walkTree(etype, columns, persister, associations, new HashSet(), session); } *************** *** 108,112 **** columns = StringHelper.prefix( ( (Loadable) persister ).getIdentifierColumnNames(), //The cast is safe because collections can't contain a 1-to-1 ! alias + '.' ); } --- 109,113 ---- columns = StringHelper.prefix( ( (Loadable) persister ).getIdentifierColumnNames(), //The cast is safe because collections can't contain a 1-to-1 ! alias + StringHelper.DOT ); } *************** *** 131,135 **** if ( !session.enableJoinedFetch() || ! persister instanceof MultiTableEntityPersister //TODO: remove this + enable outerjoin fetching ) return; --- 132,136 ---- if ( !session.enableJoinedFetch() || ! persister instanceof NormalizedEntityPersister //TODO: remove this + enable outerjoin fetching ) return; *************** *** 142,146 **** EntityType etype = (EntityType) types[i]; if ( autoEager( act.enableJoinedFetch(i), etype, session ) ) { ! String[] columns = StringHelper.prefix( range, alias + '.' ); walkTree(etype, columns, persister, associations, classPersisters, session); } --- 143,147 ---- EntityType etype = (EntityType) types[i]; if ( autoEager( act.enableJoinedFetch(i), etype, session ) ) { ! String[] columns = StringHelper.prefix( range, alias + StringHelper.DOT ); walkTree(etype, columns, persister, associations, classPersisters, session); } *************** *** 168,172 **** //TODO: remove this: ! //if ( subpersister instanceof MultiTableEntityPersister ) return; if ( !classPersisters.contains(subpersister) ) { // to avoid navigating back up bidirectional associations (and circularities) --- 169,173 ---- //TODO: remove this: ! //if ( subpersister instanceof NormalizedEntityPersister ) return; if ( !classPersisters.contains(subpersister) ) { // to avoid navigating back up bidirectional associations (and circularities) *************** *** 197,205 **** */ public final String selectString(List associations) { ! StringBuffer buf = new StringBuffer(100); for ( int i=0; i<associations.size(); i++ ) { OuterJoinableAssociation join = (OuterJoinableAssociation) associations.get(i); appendSelectString( buf, join.subpersister, join.subalias, getSuffixes()[i] ); ! if ( i<associations.size()-1 ) buf.append(", "); } return buf.toString(); --- 198,206 ---- */ public final String selectString(List associations) { ! StringBuffer buf = new StringBuffer( associations.size() * 100 ); for ( int i=0; i<associations.size(); i++ ) { OuterJoinableAssociation join = (OuterJoinableAssociation) associations.get(i); appendSelectString( buf, join.subpersister, join.subalias, getSuffixes()[i] ); ! if ( i<associations.size()-1 ) buf.append(StringHelper.COMMA_SPACE); } return buf.toString(); *************** *** 219,274 **** */ private static final void appendSelectString(StringBuffer buf, Loadable persister, String alias, String suffix) { ! ! //TODO: refactor this bit onto AbstractEntityPersister (its repeated in Query stuff) ! String[] keyCols = persister.getIdentifierColumnNames(); ! for ( int j=0; j<keyCols.length; j++) { ! buf.append(alias) ! .append('.') ! .append( keyCols[j] ) ! .append(" AS ") ! .append( StringHelper.suffix( keyCols[j], suffix ) ); ! if ( j != keyCols.length-1 ) buf.append(", "); ! } ! buf.append( persister.propertySelectClauseFragment(alias, suffix) ); ! ! } ! ! /** ! * Generate a list of column conditions of the form <tt>x.foo = ?, x.bar = ?</tt> ! */ ! protected static final String whereString(String[] columns, String alias) { ! StringBuffer buf = new StringBuffer(20); ! for ( int i=0; i<columns.length; i++ ) { ! buf.append(alias) ! .append('.') ! .append( columns[i] ) ! .append( " = ?"); ! if (i<columns.length-1) buf.append(" and "); ! } ! return buf.toString(); ! } ! ! /** ! * Generate a list of collection index and element columns ! */ ! protected static final String selectCollectionString(CollectionPersister persister, String alias) { ! StringBuffer buf = new StringBuffer(20); ! String[] selectCols = persister.getElementColumnNames(); ! for ( int i=0; i<selectCols.length; i++ ) { ! buf.append(alias) ! .append('.') ! .append( selectCols[i] ); ! if (i!=selectCols.length-1) buf.append(", "); ! } ! if ( persister.hasIndex() ) { ! String[] indexCols = persister.getIndexColumnNames(); ! for ( int i=0; i<indexCols.length; i++ ) { ! buf.append(", ") ! .append(alias) ! .append('.') ! .append( indexCols[i] ); ! } ! } ! return buf.toString(); } --- 220,225 ---- */ private static final void appendSelectString(StringBuffer buf, Loadable persister, String alias, String suffix) { ! buf.append( persister.identifierSelectClauseFragment(alias, suffix) ) ! .append( persister.propertySelectClauseFragment(alias, suffix) ); } *************** *** 283,287 **** return StringHelper.suffix( tableName.length() <=5 ? tableName : tableName.substring(0, 5), ! Integer.toString(n) + '_' ); } --- 234,238 ---- return StringHelper.suffix( tableName.length() <=5 ? tableName : tableName.substring(0, 5), ! Integer.toString(n) + StringHelper.UNDERSCORE ); } *************** *** 291,305 **** } - public String outerJoinsAfterFrom(List associations) { - return outerJoinGenerator.outerJoinStringAfterFrom(associations); - } - - public String outerJoinsAfterWhere(List associations) { - return outerJoinGenerator.outerJoinStringAfterWhere(associations); - } - public void setSuffixed(String[] suffixes) { this.suffixes = suffixes; ! } } --- 242,274 ---- } public void setSuffixed(String[] suffixes) { this.suffixes = suffixes; ! } ! ! /** ! * Generate a sequence of <tt>LEFT OUTER JOIN</tt> clauses for the given associations. ! */ ! public final OuterJoinFragment outerJoins(List associations) { ! OuterJoinFragment outerjoin = dialect.createOuterJoinFragment(); ! Iterator iter = associations.iterator(); ! while ( iter.hasNext() ) { ! OuterJoinLoader.OuterJoinableAssociation oj = (OuterJoinLoader.OuterJoinableAssociation) iter.next(); ! outerjoin.addJoin( ! oj.subpersister.getTableName(), ! oj.subalias, ! oj.foreignKeyColumns, ! oj.subpersister.getIdentifierColumnNames(), ! false ! ); ! outerjoin.addJoins( ! oj.subpersister.fromJoinFragment(oj.subalias, false), ! oj.subpersister.whereJoinFragment(oj.subalias, false) ! ); ! ! //TODO: add the persister's outerjoins ! } ! return outerjoin; ! } ! } Index: SimpleEntityLoader.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/loader/SimpleEntityLoader.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** SimpleEntityLoader.java 18 Jan 2003 09:03:54 -0000 1.6 --- SimpleEntityLoader.java 20 Jan 2003 12:48:13 -0000 1.7 *************** *** 12,15 **** --- 12,16 ---- import net.sf.hibernate.persister.Loadable; import net.sf.hibernate.type.Type; + import net.sf.hibernate.util.StringHelper; /** *************** *** 22,26 **** private final String sql; private final LockMode lockMode; ! private static final String[] NO_SUFFIX = new String[] { "" }; public SimpleEntityLoader(Loadable persister, String sql, LockMode lockMode) { --- 23,27 ---- private final String sql; private final LockMode lockMode; ! private static final String[] NO_SUFFIX = new String[] { StringHelper.EMPTY_STRING }; public SimpleEntityLoader(Loadable persister, String sql, LockMode lockMode) { |