|
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
|