1 package org.hibernate.hql.ast.tree; 3 4 import java.lang.reflect.Constructor ; 5 import java.util.ArrayList ; 6 import java.util.Iterator ; 7 import java.util.List ; 8 9 import org.hibernate.hql.antlr.SqlTokenTypes; 10 import org.hibernate.hql.ast.util.ASTAppender; 11 import org.hibernate.hql.ast.util.ASTIterator; 12 import org.hibernate.hql.ast.util.ASTPrinter; 13 import org.hibernate.type.Type; 14 15 import antlr.SemanticException; 16 import antlr.collections.AST; 17 18 23 public class SelectClause extends SelectExpressionList { 24 25 private boolean prepared = false; 26 private boolean scalarSelect; 27 28 private List fromElementsForLoad = new ArrayList (); 29 private Type[] queryReturnTypes; 31 private String [][] columnNames; 32 private ConstructorNode constructorNode; 33 private List collectionFromElements; 34 private String [] aliases; 35 36 41 public boolean isScalarSelect() { 42 return scalarSelect; 43 } 44 45 50 public List getFromElementsForLoad() { 51 return fromElementsForLoad; 52 } 53 54 59 62 63 68 public Type[] getQueryReturnTypes() { 69 return queryReturnTypes; 70 } 71 72 75 public String [] getQueryReturnAliases() { 76 return aliases; 77 } 78 79 84 public String [][] getColumnNames() { 85 return columnNames; 86 } 87 88 94 public Constructor getConstructor() { 95 return constructorNode == null ? null : constructorNode.getConstructor(); 96 } 97 98 public boolean isMap() { 99 return constructorNode == null ? false : constructorNode.isMap(); 100 } 101 102 public boolean isList() { 103 return constructorNode == null ? false : constructorNode.isList(); 104 } 105 106 112 public void initializeExplicitSelectClause(FromClause fromClause) throws SemanticException { 113 if ( prepared ) { 114 throw new IllegalStateException ( "SelectClause was already prepared!" ); 115 } 116 117 ArrayList queryReturnTypeList = new ArrayList (); 120 121 SelectExpression[] selectExpressions = collectSelectExpressions(); 125 126 for ( int i = 0; i < selectExpressions.length; i++ ) { 127 SelectExpression expr = selectExpressions[i]; 128 129 if ( expr.isConstructor() ) { 130 constructorNode = ( ConstructorNode ) expr; 131 List constructorArgumentTypeList = constructorNode.getConstructorArgumentTypeList(); 132 queryReturnTypeList.addAll( constructorArgumentTypeList ); 134 scalarSelect = true; 135 } 136 else { 137 Type type = expr.getDataType(); 138 if ( type == null ) { 139 throw new IllegalStateException ( "No data type for node: " + expr.getClass().getName() + " " 140 + new ASTPrinter( SqlTokenTypes.class ).showAsString( ( AST ) expr, "" ) ); 141 } 142 144 if ( expr.isScalar() ) { 146 scalarSelect = true; 147 } 148 149 if ( isReturnableEntity( expr ) ) { 150 fromElementsForLoad.add( expr.getFromElement() ); 151 } 152 153 queryReturnTypeList.add( type ); 155 } 156 } 157 158 initAliases(selectExpressions); 160 161 if ( !getWalker().isShallowQuery() ) { 162 List fromElements = fromClause.getProjectionList(); 164 165 ASTAppender appender = new ASTAppender( getASTFactory(), this ); int size = fromElements.size(); 167 168 Iterator iterator = fromElements.iterator(); 169 for ( int k = 0; iterator.hasNext(); k++ ) { 170 FromElement fromElement = ( FromElement ) iterator.next(); 171 172 if ( fromElement.isFetch() ) { 173 Type type = fromElement.getSelectType(); 174 addCollectionFromElement( fromElement ); 175 if ( type != null ) { 176 boolean collectionOfElements = fromElement.isCollectionOfValuesOrComponents(); 177 if ( !collectionOfElements ) { 178 fromElement.setIncludeSubclasses( true ); 180 fromElementsForLoad.add( fromElement ); 181 String text = fromElement.renderIdentifierSelect( size, k ); 184 SelectExpressionImpl generatedExpr = ( SelectExpressionImpl ) appender.append( SqlTokenTypes.SELECT_EXPR, text, false ); 185 if ( generatedExpr != null ) { 186 generatedExpr.setFromElement( fromElement ); 187 } 188 } 189 } 190 } 191 } 192 193 renderNonScalarSelects( collectSelectExpressions(), fromClause ); 196 } 197 198 if ( scalarSelect || getWalker().isShallowQuery() ) { 199 renderScalarSelects( selectExpressions, fromClause ); 201 } 202 203 finishInitialization( queryReturnTypeList ); 204 } 205 206 private void finishInitialization( ArrayList queryReturnTypeList) { 207 queryReturnTypes = ( Type[] ) queryReturnTypeList.toArray( new Type[queryReturnTypeList.size()] ); 209 initializeColumnNames(); 210 prepared = true; 211 } 212 213 private void initializeColumnNames() { 214 218 columnNames = getSessionFactoryHelper().generateColumnNames( queryReturnTypes ); 220 } 221 222 227 public void initializeDerivedSelectClause(FromClause fromClause) throws SemanticException { 228 if ( prepared ) { 229 throw new IllegalStateException ( "SelectClause was already prepared!" ); 230 } 231 List fromElements = fromClause.getProjectionList(); 232 233 ASTAppender appender = new ASTAppender( getASTFactory(), this ); int size = fromElements.size(); 235 ArrayList sqlResultTypeList = new ArrayList ( size ); 236 ArrayList queryReturnTypeList = new ArrayList ( size ); 237 238 Iterator iterator = fromElements.iterator(); 239 for ( int k = 0; iterator.hasNext(); k++ ) { 240 FromElement fromElement = ( FromElement ) iterator.next(); 241 Type type = fromElement.getSelectType(); 242 243 addCollectionFromElement( fromElement ); 244 245 if ( type != null ) { 246 boolean collectionOfElements = fromElement.isCollectionOfValuesOrComponents(); 247 if ( !collectionOfElements ) { 248 if ( !fromElement.isFetch() ) { 249 queryReturnTypeList.add( type ); 251 } 252 fromElementsForLoad.add( fromElement ); 253 sqlResultTypeList.add( type ); 254 String text = fromElement.renderIdentifierSelect( size, k ); 256 SelectExpressionImpl generatedExpr = ( SelectExpressionImpl ) appender.append( SqlTokenTypes.SELECT_EXPR, text, false ); 257 if ( generatedExpr != null ) { 258 generatedExpr.setFromElement( fromElement ); 259 } 260 } 261 } 262 } 263 264 SelectExpression[] selectExpressions = collectSelectExpressions(); 266 267 if ( getWalker().isShallowQuery() ) { 268 renderScalarSelects( selectExpressions, fromClause ); 269 } 270 else { 271 renderNonScalarSelects( selectExpressions, fromClause ); 272 } 273 finishInitialization( queryReturnTypeList ); 274 } 275 276 public static boolean VERSION2_SQL = false; 277 278 private void addCollectionFromElement(FromElement fromElement) { 279 if ( fromElement.isFetch() ) { 280 if ( fromElement.isCollectionJoin() || fromElement.getQueryableCollection() != null ) { 281 String suffix; 282 if (collectionFromElements==null) { 283 collectionFromElements = new ArrayList (); 284 suffix = VERSION2_SQL ? "__" : "0__"; 285 } 286 else { 287 suffix = Integer.toString( collectionFromElements.size() ) + "__"; 288 } 289 collectionFromElements.add( fromElement ); 290 fromElement.setCollectionSuffix( suffix ); 291 } 292 } 293 } 294 295 protected AST getFirstSelectExpression() { 296 AST n = getFirstChild(); 297 while ( n != null && ( n.getType() == SqlTokenTypes.DISTINCT || n.getType() == SqlTokenTypes.ALL ) ) { 299 n = n.getNextSibling(); 300 } 301 return n; 302 } 303 304 private boolean isReturnableEntity(SelectExpression selectExpression) throws SemanticException { 305 FromElement fromElement = selectExpression.getFromElement(); 306 boolean isFetchOrValueCollection = fromElement != null && 307 ( fromElement.isFetch() || fromElement.isCollectionOfValuesOrComponents() ); 308 if ( isFetchOrValueCollection ) { 309 return false; 310 } 311 else { 312 return selectExpression.isReturnableEntity(); 313 } 314 } 315 316 private void renderScalarSelects(SelectExpression[] se, FromClause currentFromClause) throws SemanticException { 317 if ( !currentFromClause.isSubQuery() ) { 318 for ( int i = 0; i < se.length; i++ ) { 319 SelectExpression expr = se[i]; 320 expr.setScalarColumnText( i ); } 322 } 323 } 324 325 private void initAliases(SelectExpression[] selectExpressions) { 326 if (constructorNode==null) { 327 aliases = new String [selectExpressions.length]; 328 for ( int i=0; i<selectExpressions.length; i++ ) { 329 String alias = selectExpressions[i].getAlias(); 330 aliases[i] = alias==null ? Integer.toString(i) : alias; 331 } 332 } 333 else { 334 aliases = constructorNode.getAliases(); 335 } 336 } 337 338 private void renderNonScalarSelects(SelectExpression[] selectExpressions, FromClause currentFromClause) 339 throws SemanticException { 340 ASTAppender appender = new ASTAppender( getASTFactory(), this ); 341 final int size = selectExpressions.length; 342 int nonscalarSize = 0; 343 for ( int i = 0; i < size; i++ ) { 344 if ( !selectExpressions[i].isScalar() ) nonscalarSize++; 345 } 346 347 int j = 0; 348 for ( int i = 0; i < size; i++ ) { 349 if ( !selectExpressions[i].isScalar() ) { 350 SelectExpression expr = selectExpressions[i]; 351 FromElement fromElement = expr.getFromElement(); 352 if ( fromElement != null ) { 353 renderNonScalarIdentifiers( fromElement, nonscalarSize, j, expr, appender ); 354 j++; 355 } 356 } 357 } 358 359 if ( !currentFromClause.isSubQuery() ) { 360 int k = 0; 362 for ( int i = 0; i < size; i++ ) { 363 if ( !selectExpressions[i].isScalar() ) { 364 FromElement fromElement = selectExpressions[i].getFromElement(); 365 if ( fromElement != null ) { 366 renderNonScalarProperties( appender, fromElement, nonscalarSize, k ); 367 k++; 368 } 369 } 370 } 371 } 372 } 373 374 private void renderNonScalarIdentifiers(FromElement fromElement, int nonscalarSize, int j, SelectExpression expr, ASTAppender appender) { 375 String text = fromElement.renderIdentifierSelect( nonscalarSize, j ); 376 if ( !fromElement.getFromClause().isSubQuery() ) { 377 if ( !scalarSelect && !getWalker().isShallowQuery() ) { 378 expr.setText( text ); 380 } 381 else { 382 appender.append( SqlTokenTypes.SQL_TOKEN, text, false ); 383 } 384 } 385 } 386 387 private void renderNonScalarProperties(ASTAppender appender, FromElement fromElement, int nonscalarSize, int k) { 388 String text = fromElement.renderPropertySelect( nonscalarSize, k ); 389 appender.append( SqlTokenTypes.SQL_TOKEN, text, false ); 390 if ( fromElement.getQueryableCollection() != null && fromElement.isFetch() ) { 391 text = fromElement.renderCollectionSelectFragment( nonscalarSize, k ); 392 appender.append( SqlTokenTypes.SQL_TOKEN, text, false ); 393 } 394 ASTIterator iter = new ASTIterator( fromElement ); 396 while ( iter.hasNext() ) { 397 FromElement child = ( FromElement ) iter.next(); 398 if ( child.isCollectionOfValuesOrComponents() && child.isFetch() ) { 399 text = child.renderValueCollectionSelectFragment( nonscalarSize, nonscalarSize + k ); 401 appender.append( SqlTokenTypes.SQL_TOKEN, text, false ); 402 } 403 } 404 } 405 406 public List getCollectionFromElements() { 407 return collectionFromElements; 408 } 409 } 410 | Popular Tags |