From: <one...@us...> - 2002-11-21 07:45:00
|
Update of /cvsroot/hibernate/Hibernate/cirrus/hibernate/query In directory sc8-pr-cvs1:/tmp/cvs-serv14321/cirrus/hibernate/query Modified Files: PathExpressionParser.java WhereParser.java Log Message: support for subcollections in query language: foo.bars[2]['index'], foo.bars[4].elements, foo.bars[0].size Index: PathExpressionParser.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate/cirrus/hibernate/query/PathExpressionParser.java,v retrieving revision 1.62 retrieving revision 1.63 diff -C2 -d -r1.62 -r1.63 *** PathExpressionParser.java 26 Oct 2002 16:43:27 -0000 1.62 --- PathExpressionParser.java 21 Nov 2002 07:44:57 -0000 1.63 *************** *** 44,47 **** --- 44,48 ---- private String path; private boolean skippedId; + private boolean continuation; private void addJoin(String name, String[] rhsCols, QueryTranslator q) throws QueryException { *************** *** 56,59 **** --- 57,96 ---- } } + + public String continueFromManyToMany(Class clazz, String[] joinColumns, QueryTranslator q) throws QueryException { + start(q); + continuation=true; + currentName = q.createNameFor(clazz); + q.addType( currentName, clazz.getName() ); + + join.append(" and ") + .append( joinColumns[0] ) + .append('=') + .append(currentName) + .append('.') + .append( q.getPersister(clazz).getIdentifierColumnNames()[0] ); + //TODO: composite keys! + return currentName; + } + + public String continueFromSubcollection(String role, String[] joinColumns, QueryTranslator q) throws QueryException { + start(q); + continuation=true; + collectionName = q.createNameForCollection(role); + collectionRole = role; + currentName=null; + currentProperty=null; + CollectionPersister p = q.getCollectionPersister(role); + collectionTable = p.getQualifiedTableName(); + + join.append(" and ") + .append( joinColumns[0] ) + .append('=') + .append(collectionName) + .append('.') + .append( p.getKeyColumnNames()[0] ); + //TODO: composite keys! + return collectionName; + } *************** *** 73,81 **** else { if ( dotcount==0 ) { ! if ( !q.isName(token) ) throw new QueryException("undefined alias: " + token); ! currentName=token; } else if (dotcount==1) { ! currentProperty = token; } else { // dotcount>=2 --- 110,130 ---- else { if ( dotcount==0 ) { ! if (!continuation) { ! if ( !q.isName(token) ) throw new QueryException("undefined alias: " + token); ! currentName=token; ! } } else if (dotcount==1) { ! if (currentName!=null) { ! currentProperty = token; ! } ! else if (collectionName!=null) { ! CollectionPersister p = q.getCollectionPersister(collectionRole); ! doCollectionProperty(token, p, collectionName); ! continuation = false; ! } ! else { ! throw new QueryException("unexpected"); ! } } else { // dotcount>=2 *************** *** 84,88 **** Type propertyType = getPropertyType(q); ! if (propertyType==null) throw new QueryException("unresolved property: " + currentProperty); if ( propertyType.isComponentType() ) { --- 133,139 ---- Type propertyType = getPropertyType(q); ! if (propertyType==null) { ! throw new QueryException("unresolved property: " + currentProperty); ! } if ( propertyType.isComponentType() ) { *************** *** 126,136 **** collectionRole = ( (PersistentCollectionType) propertyType ).getRole(); ! CollectionPersister memberPersister = q.getCollectionPersister(collectionRole); ! String[] colNames = memberPersister.getKeyColumnNames(); String name = q.createNameForCollection(collectionRole); addJoin(name, colNames, q); ! doCollectionProperty(token, memberPersister, name); collectionName = name; ! collectionTable = memberPersister.getQualifiedTableName(); currentName=null; currentProperty=null; --- 177,187 ---- collectionRole = ( (PersistentCollectionType) propertyType ).getRole(); ! CollectionPersister p = q.getCollectionPersister(collectionRole); ! String[] colNames = p.getKeyColumnNames(); String name = q.createNameForCollection(collectionRole); addJoin(name, colNames, q); ! doCollectionProperty(token, p, name); collectionName = name; ! collectionTable = p.getQualifiedTableName(); currentName=null; currentProperty=null; *************** *** 198,206 **** expectingCollectionIndex = false; skippedId = false; } public void start(QueryTranslator q) { ! reset(); ! path = ""; } --- 249,260 ---- expectingCollectionIndex = false; skippedId = false; + continuation = false; } public void start(QueryTranslator q) { ! if (!continuation) { ! reset(); ! path = ""; ! } } *************** *** 212,230 **** else { ! Type propertyType = getPropertyType(q); ! if ( propertyType!=null && propertyType.isPersistentCollectionType() ) { ! //special case: expecting a [index] ! collectionRole = ( (PersistentCollectionType) propertyType ).getRole(); CollectionPersister memberPersister = q.getCollectionPersister(collectionRole); if ( !memberPersister.hasIndex() ) throw new QueryException("unindexed collection before []"); ! String name = q.createNameForCollection(collectionRole); String[] keyCols = memberPersister.getKeyColumnNames(); ! addJoin(name, keyCols, q); String[] indexCols = memberPersister.getIndexColumnNames(); if ( indexCols.length!=1 ) throw new QueryException("composite-index appears in []"); join.append(" and ") ! .append(name) .append('.') .append( indexCols[0] ) --- 266,289 ---- else { ! if (!continuation) { ! Type propertyType = getPropertyType(q); ! if ( propertyType!=null && propertyType.isPersistentCollectionType() ) { ! collectionRole = ( (PersistentCollectionType) propertyType ).getRole(); ! collectionName = q.createNameForCollection(collectionRole); ! } ! } ! if (collectionRole!=null) { ! //special case; expecting: [index] CollectionPersister memberPersister = q.getCollectionPersister(collectionRole); if ( !memberPersister.hasIndex() ) throw new QueryException("unindexed collection before []"); ! String[] keyCols = memberPersister.getKeyColumnNames(); ! if (!continuation) addJoin(collectionName, keyCols, q); String[] indexCols = memberPersister.getIndexColumnNames(); if ( indexCols.length!=1 ) throw new QueryException("composite-index appears in []"); join.append(" and ") ! .append(collectionName) .append('.') .append( indexCols[0] ) *************** *** 232,247 **** String[] eltCols = memberPersister.getElementColumnNames(); ! if ( eltCols.length!=1 ) throw new QueryException("composite-id collection element []"); CollectionElement elem = new CollectionElement(); ! elem.elementColumn = name + '.' + eltCols[0]; elem.type = memberPersister.getElementType(); elem.isOneToMany = memberPersister.isOneToMany(); ! elem.alias = name; elem.join = join.toString(); collectionElements.addLast(elem); setExpectingCollectionIndex(); ! q.addCollection(name, collectionRole); } else { --- 291,306 ---- 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 + '.' ); elem.type = memberPersister.getElementType(); elem.isOneToMany = memberPersister.isOneToMany(); ! elem.alias = collectionName; elem.join = join.toString(); collectionElements.addLast(elem); setExpectingCollectionIndex(); ! q.addCollection(collectionName, collectionRole); } else { *************** *** 251,254 **** --- 310,317 ---- } + + //important!! + continuation=false; + } *************** *** 257,261 **** boolean isOneToMany; String alias; ! String elementColumn; String join; StringBuffer indexValue = new StringBuffer(); --- 320,324 ---- boolean isOneToMany; String alias; ! String[] elementColumns; String join; StringBuffer indexValue = new StringBuffer(); *************** *** 293,297 **** } ! public String getCollectionSubquery() throws QueryException { return new StringBuffer( "SELECT " ) .append( StringHelper.join( ", ", collectionElementColumns ) ) --- 356,361 ---- } ! public String getCollectionSubquery(String extraJoin) throws QueryException { ! if (extraJoin!=null) join.append(extraJoin); return new StringBuffer( "SELECT " ) .append( StringHelper.join( ", ", collectionElementColumns ) ) Index: WhereParser.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate/cirrus/hibernate/query/WhereParser.java,v retrieving revision 1.39 retrieving revision 1.40 diff -C2 -d -r1.39 -r1.40 *** WhereParser.java 20 Nov 2002 07:06:44 -0000 1.39 --- WhereParser.java 21 Nov 2002 07:44:57 -0000 1.40 *************** *** 16,19 **** --- 16,20 ---- import cirrus.hibernate.type.EntityType; import cirrus.hibernate.type.LiteralType; + import cirrus.hibernate.type.PersistentCollectionType; import cirrus.hibernate.type.Type; import cirrus.hibernate.type.TypeFactory; *************** *** 148,152 **** private LinkedList nots = new LinkedList(); //were an odd or even number of NOTs encountered private LinkedList joins = new LinkedList(); //the join string built up by compound paths inside this expression ! private LinkedList booleanTests = new LinkedList(); //a flag indicating if the subexpression is known to be boolean public void token(String token, QueryTranslator q) throws QueryException { --- 149,177 ---- private LinkedList nots = new LinkedList(); //were an odd or even number of NOTs encountered private LinkedList joins = new LinkedList(); //the join string built up by compound paths inside this expression ! private LinkedList booleanTests = new LinkedList(); //a flag indicating if the subexpression is known to be boolean ! private String collectionJoin; ! ! private String getElementName(PathExpressionParser.CollectionElement element, QueryTranslator q) throws QueryException { ! String name; ! if ( element.isOneToMany ) { ! name = element.alias; ! } ! else { ! Type type = element.type; ! Class clazz; ! if ( type.isEntityType() ) { //ie. a many-to-many ! clazz = ( (EntityType) type ).getPersistentClass(); ! name = pathExpressionParser.continueFromManyToMany(clazz, element.elementColumns, q); ! } ! else if ( type.isPersistentCollectionType() ) { //ie. a subcollection ! String role = ( (PersistentCollectionType) type ).getRole(); ! name = pathExpressionParser.continueFromSubcollection(role, element.elementColumns, q); ! } ! else { ! throw new QueryException("illegally dereferenced collection element"); ! } ! } ! return name; ! } public void token(String token, QueryTranslator q) throws QueryException { *************** *** 156,160 **** //Cope with [,] ! if ( token.equals("[") ) { if (expectingIndex==0) throw new QueryException("unexpected ["); return; --- 181,186 ---- //Cope with [,] ! if ( token.equals("[") && !expectingPathContinuation ) { ! expectingPathContinuation = false; if (expectingIndex==0) throw new QueryException("unexpected ["); return; *************** *** 175,201 **** if ( token.startsWith(".") ) { // the path expression continues after a ] ! String name; ! if ( element.isOneToMany ) { ! name = element.alias; ! } ! else { ! Type type = element.type; ! Class clazz ; ! if ( type.isEntityType() ) { ! clazz = ( (EntityType) type ).getPersistentClass(); ! name = q.createNameFor(clazz); ! q.addType( name, clazz.getName() ); ! } ! else { ! throw new QueryException("illegally dereferenced collection element"); ! } ! //TODO: move this to PathExpressionParser.end() ! addToCurrentJoin(" and "); ! addToCurrentJoin(element.elementColumn); ! addToCurrentJoin("="); ! addToCurrentJoin( name + '.' + q.getPersister(clazz).getIdentifierColumnNames()[0] ); ! } ! ! token(name + token, q); // careful with this! addToCurrentJoin(element.join); --- 201,205 ---- if ( token.startsWith(".") ) { // the path expression continues after a ] ! doPathExpression( getElementName(element, q) + token, q ); // careful with this! addToCurrentJoin(element.join); *************** *** 204,209 **** } else { // the path expression ends at the ] ! appendToken( q, element.elementColumn ); addToCurrentJoin(element.join); addToCurrentJoin( element.indexValue.toString() ); --- 208,220 ---- } + else if ( token.equals("[") ) { + doPathExpression( getElementName(element, q), q ); + addToCurrentJoin(element.join); + addToCurrentJoin( element.indexValue.toString() ); + return; //NOTE: EARLY EXIT! + } else { // the path expression ends at the ] ! if ( element.elementColumns.length!=1 ) throw new QueryException("path expression ended in composite collection element"); ! appendToken( q, element.elementColumns[0] ); addToCurrentJoin(element.join); addToCurrentJoin( element.indexValue.toString() ); *************** *** 293,297 **** expectingPathContinuation=false; PathExpressionParser.CollectionElement element = pathExpressionParser.lastCollectionElement(); ! appendToken( q, element.elementColumn ); addToCurrentJoin(element.join); addToCurrentJoin( element.indexValue.toString() ); --- 304,309 ---- expectingPathContinuation=false; PathExpressionParser.CollectionElement element = pathExpressionParser.lastCollectionElement(); ! if ( element.elementColumns.length!=1 ) throw new QueryException("path expression ended in composite collection element"); ! appendToken( q, element.elementColumns[0] ); addToCurrentJoin(element.join); addToCurrentJoin( element.indexValue.toString() ); *************** *** 343,370 **** appendToken(q, "("); }*/ ! ! private void doToken(String token, QueryTranslator q) throws QueryException { ! if ( q.isName( StringHelper.root(token) ) ) { //path expression ! StringTokenizer tokens = new StringTokenizer(token, ".", true); ! pathExpressionParser.start(q); ! while( tokens.hasMoreTokens() ) { ! pathExpressionParser.token( tokens.nextToken(), q); ! } ! pathExpressionParser.end(q); ! if ( pathExpressionParser.isCollectionValued() ) { ! openExpression(q, ""); ! appendToken( q, pathExpressionParser.getCollectionSubquery() ); ! q.addIdentifierSpace( pathExpressionParser.getCollectionTable() ); ! closeExpression(q, ""); } else { ! if ( pathExpressionParser.isExpectingCollectionIndex() ) { ! expectingIndex++; ! } ! else { ! addToCurrentJoin( pathExpressionParser.getWhereJoin() ); ! appendToken( q, pathExpressionParser.getWhereColumn() ); ! } } } else if ( token.startsWith(ParserHelper.HQL_VARIABLE_PREFIX) ) { //named query parameter --- 355,387 ---- appendToken(q, "("); }*/ ! ! private void doPathExpression(String token, QueryTranslator q) throws QueryException { ! StringTokenizer tokens = new StringTokenizer(token, ".", true); ! pathExpressionParser.start(q); ! while( tokens.hasMoreTokens() ) { ! pathExpressionParser.token( tokens.nextToken(), q); ! } ! pathExpressionParser.end(q); ! if ( pathExpressionParser.isCollectionValued() ) { ! openExpression(q, ""); ! appendToken( q, pathExpressionParser.getCollectionSubquery(collectionJoin) ); ! q.addIdentifierSpace( pathExpressionParser.getCollectionTable() ); ! closeExpression(q, ""); ! collectionJoin = null; ! } ! else { ! if ( pathExpressionParser.isExpectingCollectionIndex() ) { ! expectingIndex++; } else { ! addToCurrentJoin( pathExpressionParser.getWhereJoin() ); ! appendToken( q, pathExpressionParser.getWhereColumn() ); } + } + } + + private void doToken(String token, QueryTranslator q) throws QueryException { + if ( q.isName( StringHelper.root(token) ) ) { //path expression + doPathExpression(token, q); } else if ( token.startsWith(ParserHelper.HQL_VARIABLE_PREFIX) ) { //named query parameter |