1 package org.hibernate.hql.ast.tree; 3 4 import java.util.List ; 5 6 import org.hibernate.dialect.function.SQLFunction; 7 import org.hibernate.hql.antlr.SqlTokenTypes; 8 import org.hibernate.hql.ast.util.ColumnHelper; 9 import org.hibernate.persister.collection.QueryableCollection; 10 import org.hibernate.persister.entity.Queryable; 11 import org.hibernate.sql.JoinFragment; 12 import org.hibernate.type.CollectionType; 13 import org.hibernate.type.Type; 14 import org.hibernate.util.StringHelper; 15 16 import antlr.SemanticException; 17 import antlr.collections.AST; 18 19 26 public class IdentNode extends FromReferenceNode implements SelectExpression { 27 28 private static final int UNKNOWN = 0; 29 private static final int PROPERTY_REF = 1; 30 private static final int COMPONENT_REF = 2; 31 32 private boolean nakedPropertyRef = false; 33 private boolean root; 34 35 public void setRoot() { 36 root = true; 37 } 38 39 public void resolveIndex(AST parent) throws SemanticException { 40 if ( !( isResolved() && nakedPropertyRef ) ) { 48 throw new UnsupportedOperationException (); 49 } 50 51 String propertyName = getOriginalText(); 52 if ( !getDataType().isCollectionType() ) { 53 throw new SemanticException( "Collection expected; [" + propertyName + "] does not refer to a collection property" ); 54 } 55 56 CollectionType type = ( CollectionType ) getDataType(); 58 String role = type.getRole(); 59 QueryableCollection queryableCollection = getSessionFactoryHelper().requireQueryableCollection( role ); 60 61 String alias = null; String columnTableAlias = getFromElement().getTableAlias(); 63 int joinType = JoinFragment.INNER_JOIN; 64 boolean fetch = false; 65 66 FromElementFactory factory = new FromElementFactory( 67 getWalker().getCurrentFromClause(), 68 getFromElement(), 69 propertyName, 70 alias, 71 getFromElement().toColumns( columnTableAlias, propertyName, false ), 72 true 73 ); 74 FromElement elem = factory.createCollection( queryableCollection, role, joinType, fetch, true ); 75 setFromElement( elem ); 76 getWalker().addQuerySpaces( queryableCollection.getCollectionSpaces() ); } 78 79 public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent) { 80 if ( !isResolved() ) { 81 if ( getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) { 82 if ( resolveAsAlias() ) { 83 setResolved(); 84 } 86 } 87 else if ( parent != null && parent.getType() == SqlTokenTypes.DOT ) { 88 DotNode dot = ( DotNode ) parent; 89 if ( parent.getFirstChild() == this ) { 90 if ( resolveAsNakedComponentPropertyRefLHS( dot ) ) { 91 setResolved(); 93 } 94 } 95 else { 96 if ( resolveAsNakedComponentPropertyRefRHS( dot ) ) { 97 setResolved(); 99 } 100 } 101 } 102 else { 103 int result = resolveAsNakedPropertyRef(); 104 if ( result == PROPERTY_REF ) { 105 setResolved(); 107 } 108 else if ( result == COMPONENT_REF ) { 109 return; 112 } 113 } 114 115 if ( !isResolved() ) { 121 if ( !getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) { 123 try { 124 getWalker().getLiteralProcessor().processConstant( this ); 125 } 126 catch( Throwable ignore ) { 127 } 129 } 130 } 131 } 132 } 133 134 private boolean resolveAsAlias() { 135 FromElement element = getWalker().getCurrentFromClause().getFromElement( getText() ); 137 if ( element != null ) { 138 setFromElement( element ); 139 setText( element.getIdentityColumn() ); 140 setType( SqlTokenTypes.ALIAS_REF ); 141 return true; 142 } 143 return false; 144 } 145 146 private int resolveAsNakedPropertyRef() { 147 FromElement fromElement = locateSingleFromElement(); 148 if ( fromElement == null ) { 149 return UNKNOWN; 150 } 151 Queryable persister = fromElement.getQueryable(); 152 if ( persister == null ) { 153 return UNKNOWN; 154 } 155 156 String property = getText(); 157 Type propertyType = null; 158 try { 159 propertyType = fromElement.getPropertyType( getText(), property ); 160 } 161 catch( Throwable t ) { 162 return UNKNOWN; 164 } 165 166 if ( propertyType.isComponentType() && !root ) { 167 return COMPONENT_REF; 168 } 169 170 setFromElement( fromElement ); 171 172 if ( persister != null ) { 173 String [] columns = getWalker().isSelectStatement() 174 ? persister.toColumns( fromElement.getTableAlias(), property ) 175 : persister.toColumns( property ); 176 String text = StringHelper.join( ", ", columns ); 177 setText( columns.length==1 ? text : "(" + text + ")" ); 178 setType( SqlTokenTypes.SQL_TOKEN ); 179 } 180 181 super.setDataType( propertyType ); 183 nakedPropertyRef = true; 184 185 return PROPERTY_REF; 186 } 187 188 private boolean resolveAsNakedComponentPropertyRefLHS(DotNode parent) { 189 FromElement fromElement = locateSingleFromElement(); 190 if ( fromElement == null ) { 191 return false; 192 } 193 194 String propertyPath = getText() + "." + getNextSibling().getText(); 195 Type propertyType = null; try { 197 propertyType = fromElement.getPropertyType( getText(), propertyPath ); 200 } 201 catch( Throwable t ) { 202 return false; 204 } 205 206 setFromElement( fromElement ); 207 parent.setPropertyPath( propertyPath ); 208 parent.setDataType( propertyType ); 209 210 return true; 211 } 212 213 private boolean resolveAsNakedComponentPropertyRefRHS(DotNode parent) { 214 FromElement fromElement = locateSingleFromElement(); 215 if ( fromElement == null ) { 216 return false; 217 } 218 219 Type propertyType = null; 220 String propertyPath = parent.getLhs().getText() + "." + getText(); 221 try { 222 propertyType = fromElement.getPropertyType( getText(), propertyPath ); 225 } 226 catch( Throwable t ) { 227 return false; 229 } 230 231 setFromElement( fromElement ); 232 233 super.setDataType( propertyType ); 235 nakedPropertyRef = true; 236 237 return true; 238 } 239 240 private FromElement locateSingleFromElement() { 241 List fromElements = getWalker().getCurrentFromClause().getFromElements(); 242 if ( fromElements == null || fromElements.size() != 1 ) { 243 return null; 245 } 246 FromElement element = ( FromElement ) fromElements.get(0); 247 if ( element.getClassAlias() != null ) { 248 return null; 250 } 251 return element; 252 } 253 254 public Type getDataType() { 255 Type type = super.getDataType(); 256 if (type!=null) return type; 257 FromElement fe = getFromElement(); 258 if (fe!=null) return fe.getDataType(); 259 SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction( getText() ); 260 return sf==null ? null : sf.getReturnType(null, null); 261 } 262 263 public void setScalarColumnText(int i) throws SemanticException { 264 if ( nakedPropertyRef ) { 265 ColumnHelper.generateSingleScalarColumn( this, i ); 268 } 269 else { 270 FromElement fe = getFromElement(); 271 if (fe!=null) { 272 setText( fe.renderScalarIdentifierSelect( i ) ); 273 } 274 else { 275 ColumnHelper.generateSingleScalarColumn( this, i ); 276 } 277 } 278 } 279 280 public String getDisplayText() { 281 StringBuffer buf = new StringBuffer (); 282 283 if ( getType() == SqlTokenTypes.ALIAS_REF ) { 284 buf.append( "{alias=" ).append( getOriginalText() ); 285 if ( getFromElement() == null ) { 286 buf.append( ", no from element" ); 287 } 288 else { 289 buf.append( ", className=" ).append( getFromElement().getClassName() ); 290 buf.append( ", tableAlias=" ).append( getFromElement().getTableAlias() ); 291 } 292 buf.append( "}" ); 293 } 294 else { 295 buf.append( "{originalText=" + getOriginalText() ).append( "}" ); 296 } 297 return buf.toString(); 298 } 299 300 } 301
| Popular Tags
|