1 package org.hibernate.hql.ast; 3 4 import java.io.Serializable ; 5 import java.util.ArrayList ; 6 import java.util.Date ; 7 import java.util.HashMap ; 8 import java.util.HashSet ; 9 import java.util.Iterator ; 10 import java.util.List ; 11 import java.util.Map ; 12 import java.util.Set ; 13 14 import org.apache.commons.logging.Log; 15 import org.apache.commons.logging.LogFactory; 16 import org.hibernate.QueryException; 17 import org.hibernate.engine.JoinSequence; 18 import org.hibernate.engine.ParameterBinder; 19 import org.hibernate.engine.SessionFactoryImplementor; 20 import org.hibernate.hql.QueryTranslator; 21 import org.hibernate.hql.antlr.HqlSqlBaseWalker; 22 import org.hibernate.hql.antlr.HqlSqlTokenTypes; 23 import org.hibernate.hql.antlr.HqlTokenTypes; 24 import org.hibernate.hql.antlr.SqlTokenTypes; 25 import org.hibernate.hql.ast.tree.AssignmentSpecification; 26 import org.hibernate.hql.ast.tree.CollectionFunction; 27 import org.hibernate.hql.ast.tree.ConstructorNode; 28 import org.hibernate.hql.ast.tree.DeleteStatement; 29 import org.hibernate.hql.ast.tree.DotNode; 30 import org.hibernate.hql.ast.tree.FromClause; 31 import org.hibernate.hql.ast.tree.FromElement; 32 import org.hibernate.hql.ast.tree.FromReferenceNode; 33 import org.hibernate.hql.ast.tree.IdentNode; 34 import org.hibernate.hql.ast.tree.IndexNode; 35 import org.hibernate.hql.ast.tree.InsertStatement; 36 import org.hibernate.hql.ast.tree.IntoClause; 37 import org.hibernate.hql.ast.tree.MethodNode; 38 import org.hibernate.hql.ast.tree.ParameterNode; 39 import org.hibernate.hql.ast.tree.QueryNode; 40 import org.hibernate.hql.ast.tree.ResolvableNode; 41 import org.hibernate.hql.ast.tree.RestrictableStatement; 42 import org.hibernate.hql.ast.tree.SelectClause; 43 import org.hibernate.hql.ast.tree.SelectExpression; 44 import org.hibernate.hql.ast.tree.UpdateStatement; 45 import org.hibernate.hql.ast.util.ASTPrinter; 46 import org.hibernate.hql.ast.util.ASTUtil; 47 import org.hibernate.hql.ast.util.AliasGenerator; 48 import org.hibernate.hql.ast.util.JoinProcessor; 49 import org.hibernate.hql.ast.util.LiteralProcessor; 50 import org.hibernate.hql.ast.util.SessionFactoryHelper; 51 import org.hibernate.hql.ast.util.SyntheticAndFactory; 52 import org.hibernate.id.IdentifierGenerator; 53 import org.hibernate.id.PostInsertIdentifierGenerator; 54 import org.hibernate.id.SequenceGenerator; 55 import org.hibernate.param.NamedParameterSpecification; 56 import org.hibernate.param.ParameterSpecification; 57 import org.hibernate.param.PositionalParameterSpecification; 58 import org.hibernate.param.VersionTypeSeedParameterSpecification; 59 import org.hibernate.persister.collection.QueryableCollection; 60 import org.hibernate.persister.entity.Queryable; 61 import org.hibernate.sql.JoinFragment; 62 import org.hibernate.type.AssociationType; 63 import org.hibernate.type.Type; 64 import org.hibernate.type.VersionType; 65 import org.hibernate.usertype.UserVersionType; 66 import org.hibernate.util.ArrayHelper; 67 68 import antlr.ASTFactory; 69 import antlr.RecognitionException; 70 import antlr.SemanticException; 71 import antlr.collections.AST; 72 73 84 public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, ParameterBinder.NamedParameterSource { 85 private static Log log = LogFactory.getLog( HqlSqlWalker.class ); 86 87 90 private SessionFactoryHelper sessionFactoryHelper; 91 92 95 private LiteralProcessor literalProcessor; 96 97 100 private ParseErrorHandler parseErrorHandler; 101 102 105 private FromClause currentFromClause = null; 106 107 110 private SelectClause selectClause; 111 112 115 private AliasGenerator aliasGenerator = new AliasGenerator(); 116 117 120 private Set querySpaces = new HashSet (); 121 122 125 private Map tokenReplacements; 126 127 private QueryTranslatorImpl queryTranslatorImpl; 128 129 132 private int parameterCount; 133 134 137 private Map namedParameters = new HashMap (); 138 139 142 private String filterCollectionRole; 143 144 147 private HqlParser hqlParser; 148 149 private ASTPrinter printer; 150 151 154 private int impliedJoinType; 155 156 private ArrayList parameters = new ArrayList (); 157 private int numberOfParametersInSetClause; 158 private int positionalParameterCount; 159 160 private ArrayList assignmentSpecifications = new ArrayList (); 161 162 172 public HqlSqlWalker(QueryTranslatorImpl qti, 173 SessionFactoryImplementor sfi, 174 HqlParser parser, 175 Map tokenReplacements, 176 String collectionRole) { 177 setASTFactory( new SqlASTFactory( this ) ); 178 this.parseErrorHandler = new ErrorCounter(); 180 this.queryTranslatorImpl = qti; 181 this.sessionFactoryHelper = new SessionFactoryHelper( sfi ); 182 this.literalProcessor = new LiteralProcessor( this ); 183 this.tokenReplacements = tokenReplacements; 184 this.filterCollectionRole = collectionRole; 185 this.hqlParser = parser; 186 this.printer = new ASTPrinter( SqlTokenTypes.class ); 187 } 188 189 190 protected void prepareFromClauseInputTree(AST fromClauseInput) { 191 if ( isFilter() && !isSubQuery() ) { 194 QueryableCollection persister = sessionFactoryHelper.getCollectionPersister( filterCollectionRole ); 195 Type collectionElementType = persister.getElementType(); 196 if ( !collectionElementType.isEntityType() ) { 197 throw new QueryException( "collection of values in filter: this" ); 198 } 199 200 String collectionElementEntityName = persister.getElementPersister().getEntityName(); 201 ASTFactory inputAstFactory = hqlParser.getASTFactory(); 202 AST fromElement = ASTUtil.create( inputAstFactory, HqlTokenTypes.FILTER_ENTITY, collectionElementEntityName ); 203 ASTUtil.createSibling( inputAstFactory, HqlTokenTypes.ALIAS, "this", fromElement ); 204 fromClauseInput.addChild( fromElement ); 205 if ( log.isDebugEnabled() ) { 207 log.debug( "prepareFromClauseInputTree() : Filter - Added 'this' as a from element..." ); 208 } 209 queryTranslatorImpl.showHqlAst( hqlParser.getAST() ); 210 } 211 } 212 213 private boolean isFilter() { 214 return filterCollectionRole != null; 215 } 216 217 public SessionFactoryHelper getSessionFactoryHelper() { 218 return sessionFactoryHelper; 219 } 220 221 public Map getTokenReplacements() { 222 return tokenReplacements; 223 } 224 225 public AliasGenerator getAliasGenerator() { 226 return aliasGenerator; 227 } 228 229 public FromClause getCurrentFromClause() { 230 return currentFromClause; 231 } 232 233 public ParseErrorHandler getParseErrorHandler() { 234 return parseErrorHandler; 235 } 236 237 public void reportError(RecognitionException e) { 238 parseErrorHandler.reportError( e ); } 240 241 public void reportError(String s) { 242 parseErrorHandler.reportError( s ); } 244 245 public void reportWarning(String s) { 246 parseErrorHandler.reportWarning( s ); 247 } 248 249 255 public Set getQuerySpaces() { 256 return querySpaces; 257 } 258 259 protected AST createFromElement(String path, AST alias, AST propertyFetch) throws SemanticException { 260 FromElement fromElement = currentFromClause.addFromElement( path, alias ); 261 fromElement.setAllPropertyFetch(propertyFetch!=null); 262 return fromElement; 263 } 264 265 protected AST createFromFilterElement(AST filterEntity, AST alias) throws SemanticException { 266 FromElement fromElement = currentFromClause.addFromElement( filterEntity.getText(), alias ); 267 FromClause fromClause = fromElement.getFromClause(); 268 QueryableCollection persister = sessionFactoryHelper.getCollectionPersister( filterCollectionRole ); 269 String [] keyColumnNames = persister.getKeyColumnNames(); 272 String fkTableAlias = persister.isOneToMany() 273 ? fromElement.getTableAlias() 274 : fromClause.getAliasGenerator().createName( filterCollectionRole ); 275 JoinSequence join = sessionFactoryHelper.createJoinSequence(); 276 join.setRoot( persister, fkTableAlias ); 277 if ( !persister.isOneToMany() ) { 278 join.addJoin( ( AssociationType ) persister.getElementType(), 279 fromElement.getTableAlias(), 280 JoinFragment.INNER_JOIN, 281 persister.getElementColumnNames( fkTableAlias ) ); 282 } 283 join.addCondition( fkTableAlias, keyColumnNames, " = ?" ); 284 fromElement.setJoinSequence( join ); 285 fromElement.setFilter( true ); 286 if ( log.isDebugEnabled() ) { 287 log.debug( "createFromFilterElement() : processed filter FROM element." ); 288 } 289 return fromElement; 290 } 291 292 protected void createFromJoinElement( 293 AST path, 294 AST alias, 295 int joinType, 296 AST fetchNode, 297 AST propertyFetch, 298 AST with) throws SemanticException { 299 boolean fetch = ( fetchNode != null ) ? true : false; 300 if ( path.getType() != SqlTokenTypes.DOT ) { 302 throw new SemanticException( "Path expected for join!" ); 303 } 304 DotNode dot = ( DotNode ) path; 305 int hibernateJoinType = JoinProcessor.toHibernateJoinType( joinType ); 306 dot.setJoinType( hibernateJoinType ); dot.setFetch( fetch ); 308 dot.resolve( true, false, alias == null ? null : alias.getText() ); 311 FromElement fromElement = dot.getImpliedJoin(); 312 fromElement.setAllPropertyFetch(propertyFetch!=null); 313 314 if ( with != null ) { 315 if ( fetch ) { 316 throw new SemanticException( "with-clause not allowed on fetched associations; use filters" ); 317 } 318 handleWithFragment( fromElement, with ); 319 } 320 321 if ( log.isDebugEnabled() ) { 322 log.debug( "createFromJoinElement() : " + getASTPrinter().showAsString( fromElement, "-- join tree --" ) ); 323 } 324 } 325 326 private void handleWithFragment(FromElement fromElement, AST hqlWithNode) throws SemanticException 327 { 328 try { 329 withClause( hqlWithNode ); 330 AST hqlSqlWithNode = returnAST; 331 SqlGenerator sql = new SqlGenerator( getSessionFactoryHelper().getFactory() ); 332 sql.whereExpr( hqlSqlWithNode.getFirstChild() ); 333 fromElement.setAdHocOnClauseFragment( "(" + sql.getSQL() + ")" ); 334 335 } catch ( Exception e) { 336 throw new SemanticException( e.getMessage() ); 337 } 338 } 339 340 346 protected void pushFromClause(AST fromNode, AST inputFromNode) { 347 FromClause newFromClause = ( FromClause ) fromNode; 348 newFromClause.setParentFromClause( currentFromClause ); 349 currentFromClause = newFromClause; 350 } 351 352 355 private void popFromClause() { 356 currentFromClause = currentFromClause.getParentFromClause(); 357 } 358 359 protected void lookupAlias(AST aliasRef) 360 throws SemanticException { 361 FromElement alias = currentFromClause.getFromElement( aliasRef.getText() ); 362 FromReferenceNode aliasRefNode = ( FromReferenceNode ) aliasRef; 363 aliasRefNode.setFromElement( alias ); 364 } 365 366 protected void setImpliedJoinType(int joinType) { 367 impliedJoinType = JoinProcessor.toHibernateJoinType( joinType ); 368 } 369 370 public int getImpliedJoinType() { 371 return impliedJoinType; 372 } 373 374 protected AST lookupProperty(AST dot, boolean root, boolean inSelect) throws SemanticException { 375 DotNode dotNode = ( DotNode ) dot; 376 FromReferenceNode lhs = dotNode.getLhs(); 377 AST rhs = lhs.getNextSibling(); 378 switch ( rhs.getType() ) { 379 case SqlTokenTypes.ELEMENTS: 380 case SqlTokenTypes.INDICES: 381 if ( log.isDebugEnabled() ) { 382 log.debug( "lookupProperty() " + dotNode.getPath() + " => " + rhs.getText() + "(" + lhs.getPath() + ")" ); 383 } 384 CollectionFunction f = ( CollectionFunction ) rhs; 385 f.setFirstChild( lhs ); 387 lhs.setNextSibling( null ); 388 dotNode.setFirstChild( f ); 389 resolve( lhs ); f.resolve( inSelect ); return f; 392 default: 393 dotNode.resolveFirstChild(); 395 return dotNode; 396 } 397 } 398 399 protected boolean isNonQualifiedPropertyRef(AST ident) { 400 final String identText = ident.getText(); 401 if ( currentFromClause.isFromElementAlias( identText ) ) { 402 return false; 403 } 404 405 List fromElements = currentFromClause.getExplicitFromElements(); 406 if ( fromElements.size() == 1 ) { 407 final FromElement fromElement = ( FromElement ) fromElements.get( 0 ); 408 try { 409 log.trace( "attempting to resolve property [" + identText + "] as a non-qualified ref" ); 410 return fromElement.getPropertyMapping( identText ).toType( identText ) != null; 411 } 412 catch( QueryException e ) { 413 } 415 } 416 417 return false; 418 } 419 420 protected AST lookupNonQualifiedProperty(AST property) throws SemanticException { 421 final FromElement fromElement = ( FromElement ) currentFromClause.getExplicitFromElements().get( 0 ); 422 AST syntheticDotNode = generateSyntheticDotNodeForNonQualifiedPropertyRef( property, fromElement ); 423 return lookupProperty( syntheticDotNode, false, getCurrentClauseType() == HqlSqlTokenTypes.SELECT ); 424 } 425 426 private AST generateSyntheticDotNodeForNonQualifiedPropertyRef(AST property, FromElement fromElement) { 427 AST dot = getASTFactory().create( DOT, "{non-qualified-property-ref}" ); 428 ( ( DotNode ) dot ).setPropertyPath( ( ( FromReferenceNode ) property ).getPath() ); 430 431 IdentNode syntheticAlias = ( IdentNode ) getASTFactory().create( IDENT, "{synthetic-alias}" ); 432 syntheticAlias.setFromElement( fromElement ); 433 syntheticAlias.setResolved(); 434 435 dot.setFirstChild( syntheticAlias ); 436 dot.addChild( property ); 437 438 return dot; 439 } 440 441 protected void processQuery(AST select, AST query) throws SemanticException { 442 if ( log.isDebugEnabled() ) { 443 log.debug( "processQuery() : " + query.toStringTree() ); 444 } 445 446 try { 447 QueryNode qn = ( QueryNode ) query; 448 449 boolean explicitSelect = select != null && select.getNumberOfChildren() > 0; 451 452 if ( !explicitSelect ) { 453 createSelectClauseFromFromClause( qn ); 459 } 460 else { 461 useSelectClause( select ); 464 } 465 466 JoinProcessor joinProcessor = new JoinProcessor( astFactory, queryTranslatorImpl ); 469 joinProcessor.processJoins( qn ); 470 471 Iterator itr = qn.getFromClause().getProjectionList().iterator(); 473 while ( itr.hasNext() ) { 474 final FromElement fromElement = ( FromElement ) itr.next(); 475 if ( fromElement.isFetch() && fromElement.getQueryableCollection() != null ) { 477 if ( fromElement.getQueryableCollection().hasOrdering() ) { 481 String orderByFragment = fromElement 482 .getQueryableCollection() 483 .getSQLOrderByString( fromElement.getCollectionTableAlias() ); 484 qn.getOrderByClause().addOrderFragment( orderByFragment ); 485 } 486 } 487 } 488 } 489 finally { 490 popFromClause(); 491 } 492 } 493 494 protected void postProcessDML(RestrictableStatement statement) throws SemanticException { 495 statement.getFromClause().resolve(); 496 497 FromElement fromElement = ( FromElement ) statement.getFromClause().getFromElements().get( 0 ); 498 Queryable persister = fromElement.getQueryable(); 499 fromElement.setText( persister.getTableName() ); 501 502 if ( persister.getDiscriminatorType() != null ) { 505 new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment( 506 statement, 507 persister, 508 java.util.Collections.EMPTY_MAP, 509 fromElement.getTableAlias() 510 ); 511 } 512 513 } 514 515 protected void postProcessUpdate(AST update) throws SemanticException { 516 UpdateStatement updateStatement = ( UpdateStatement ) update; 517 518 postProcessDML( updateStatement ); 519 } 520 521 protected void postProcessDelete(AST delete) throws SemanticException { 522 postProcessDML( ( DeleteStatement ) delete ); 523 } 524 525 public static boolean supportsIdGenWithBulkInsertion(IdentifierGenerator generator) { 526 return SequenceGenerator.class.isAssignableFrom( generator.getClass() ) 527 || PostInsertIdentifierGenerator.class.isAssignableFrom( generator.getClass() ); 528 } 529 530 protected void postProcessInsert(AST insert) throws SemanticException, QueryException { 531 InsertStatement insertStatement = ( InsertStatement ) insert; 532 insertStatement.validate(); 533 534 SelectClause selectClause = insertStatement.getSelectClause(); 535 Queryable persister = insertStatement.getIntoClause().getQueryable(); 536 537 if ( !insertStatement.getIntoClause().isExplicitIdInsertion() ) { 538 IdentifierGenerator generator = persister.getIdentifierGenerator(); 543 if ( !supportsIdGenWithBulkInsertion( generator ) ) { 544 throw new QueryException( "can only generate ids as part of bulk insert with either sequence or post-insert style generators" ); 545 } 546 547 AST idSelectExprNode = null; 548 549 if ( SequenceGenerator.class.isAssignableFrom( generator.getClass() ) ) { 550 String seqName = ( String ) ( ( SequenceGenerator ) generator ).generatorKey(); 551 String nextval = sessionFactoryHelper.getFactory().getDialect().getSelectSequenceNextValString( seqName ); 552 idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, nextval ); 553 } 554 else { 555 String idInsertString = sessionFactoryHelper.getFactory().getDialect().getIdentityInsertString(); 556 if ( idInsertString != null ) { 557 idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, idInsertString ); 558 } 559 } 560 561 if ( idSelectExprNode != null ) { 562 AST currentFirstSelectExprNode = selectClause.getFirstChild(); 563 selectClause.setFirstChild( idSelectExprNode ); 564 idSelectExprNode.setNextSibling( currentFirstSelectExprNode ); 565 566 insertStatement.getIntoClause().prependIdColumnSpec(); 567 } 568 } 569 570 if ( persister.isVersioned() && !insertStatement.getIntoClause().isExplicitVersionInsertion() ) { 571 VersionType versionType = persister.getVersionType(); 573 574 AST versionValue = getASTFactory().create( HqlSqlTokenTypes.PARAM, "?" ); 575 ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification( versionType ); 576 ( ( ParameterNode ) versionValue ).setHqlParameterSpecification( paramSpec ); 577 parameters.add( 0, paramSpec ); 578 579 AST currentFirstSelectExprNode = selectClause.getFirstChild(); 580 selectClause.setFirstChild( versionValue ); 581 versionValue.setNextSibling( currentFirstSelectExprNode ); 582 583 insertStatement.getIntoClause().prependVersionColumnSpec(); 584 } 585 586 if ( insertStatement.getIntoClause().isDiscriminated() ) { 587 String sqlValue = insertStatement.getIntoClause().getQueryable().getDiscriminatorSQLValue(); 588 AST discrimValue = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, sqlValue ); 589 insertStatement.getSelectClause().addChild( discrimValue ); 590 } 591 592 } 593 594 private void useSelectClause(AST select) throws SemanticException { 595 selectClause = ( SelectClause ) select; 596 selectClause.initializeExplicitSelectClause( currentFromClause ); 597 } 598 599 private void createSelectClauseFromFromClause(QueryNode qn) throws SemanticException { 600 AST select = astFactory.create( SELECT_CLAUSE, "{derived select clause}" ); 601 AST sibling = qn.getFromClause(); 602 qn.setFirstChild( select ); 603 select.setNextSibling( sibling ); 604 selectClause = ( SelectClause ) select; 605 selectClause.initializeDerivedSelectClause( currentFromClause ); 606 if ( log.isDebugEnabled() ) { 607 log.debug( "Derived SELECT clause created." ); 608 } 609 } 610 611 protected void resolve(AST node) throws SemanticException { 612 if ( node != null ) { 613 ResolvableNode r = ( ResolvableNode ) node; 615 if ( isInFunctionCall() ) { 616 r.resolveInFunctionCall( false, true ); 617 } 618 else { 619 r.resolve( false, true ); } 621 } 622 } 623 624 protected void resolveSelectExpression(AST node) throws SemanticException { 625 int type = node.getType(); 627 switch ( type ) { 628 case DOT: 629 DotNode dot = ( DotNode ) node; 630 dot.resolveSelectExpression(); 631 break; 632 case ALIAS_REF: 633 FromReferenceNode aliasRefNode = ( FromReferenceNode ) node; 635 aliasRefNode.resolve( false, false ); FromElement fromElement = aliasRefNode.getFromElement(); 638 if ( fromElement != null ) { 639 fromElement.setIncludeSubclasses( true ); 640 } 641 default: 642 break; 643 } 644 } 645 646 protected void beforeSelectClause() throws SemanticException { 647 FromClause from = getCurrentFromClause(); 649 List fromElements = from.getFromElements(); 650 for ( Iterator iterator = fromElements.iterator(); iterator.hasNext(); ) { 651 FromElement fromElement = ( FromElement ) iterator.next(); 652 fromElement.setIncludeSubclasses( false ); 653 } 654 } 655 656 protected void positionalParameter(AST parameter) throws SemanticException { 657 if ( namedParameters.size() > 0 ) { 658 throw new SemanticException( "" ); 659 } 660 PositionalParameterSpecification paramSpec = new PositionalParameterSpecification( positionalParameterCount++ ); 661 ( ( ParameterNode ) parameter ).setHqlParameterSpecification( paramSpec ); 662 parameters.add( paramSpec ); 663 } 664 665 protected void namedParameter(AST namedParameter) throws SemanticException { 666 String name = namedParameter.getText(); 667 addNamedParameter( name ); 668 namedParameter.setText( "?" ); 670 NamedParameterSpecification paramSpec = new NamedParameterSpecification( name ); 671 ( ( ParameterNode ) namedParameter ).setHqlParameterSpecification( paramSpec ); 672 parameters.add( paramSpec ); 673 } 674 675 private void addNamedParameter(String name) { 676 Integer loc = new Integer ( parameterCount++ ); 677 Object o = namedParameters.get( name ); 678 if ( o == null ) { 679 namedParameters.put( name, loc ); 680 } 681 else if ( o instanceof Integer ) { 682 ArrayList list = new ArrayList ( 4 ); 683 list.add( o ); 684 list.add( loc ); 685 namedParameters.put( name, list ); 686 } 687 else { 688 ( ( ArrayList ) o ).add( loc ); 689 } 690 } 691 692 protected void processConstant(AST constant) throws SemanticException { 693 literalProcessor.processConstant( constant ); } 695 696 protected void processBoolean(AST constant) throws SemanticException { 697 literalProcessor.processBoolean( constant ); } 699 700 protected void processIndex(AST indexOp) throws SemanticException { 701 IndexNode indexNode = ( IndexNode ) indexOp; 702 indexNode.resolve( true, true ); 703 } 704 705 protected void processFunction(AST functionCall, boolean inSelect) throws SemanticException { 706 MethodNode methodNode = ( MethodNode ) functionCall; 707 methodNode.resolve( inSelect ); 708 } 709 710 protected void processConstructor(AST constructor) throws SemanticException { 711 ConstructorNode constructorNode = ( ConstructorNode ) constructor; 712 constructorNode.prepare(); 713 } 714 715 protected void setAlias(AST selectExpr, AST ident) { 716 ((SelectExpression) selectExpr).setAlias(ident.getText()); 717 } 718 719 protected void setRoot(AST ast) { 720 ( (IdentNode) ast).setRoot(); 721 } 722 723 726 public int[] getNamedParameterLocations(String name) throws QueryException { 727 Object o = namedParameters.get( name ); 728 if ( o == null ) { 729 QueryException qe = new QueryException( QueryTranslator.ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name ); 730 qe.setQueryString( queryTranslatorImpl.getQueryString() ); 731 throw qe; 732 } 733 if ( o instanceof Integer ) { 734 return new int[]{( ( Integer ) o ).intValue()}; 735 } 736 else { 737 return ArrayHelper.toIntArray( ( ArrayList ) o ); 738 } 739 } 740 741 public void addQuerySpaces(Serializable [] spaces) { 742 for ( int i = 0; i < spaces.length; i++ ) { 743 querySpaces.add( spaces[i] ); 744 } 745 } 746 747 public Type[] getReturnTypes() { 748 return selectClause.getQueryReturnTypes(); 749 } 750 751 public String [] getReturnAliases() { 752 return selectClause.getQueryReturnAliases(); 753 } 754 755 public SelectClause getSelectClause() { 756 return selectClause; 757 } 758 759 public FromClause getFinalFromClause() { 760 return currentFromClause; 762 } 763 764 public boolean isShallowQuery() { 765 return queryTranslatorImpl.isShallowQuery(); 766 } 767 768 public Map getEnabledFilters() { 769 return queryTranslatorImpl.getEnabledFilters(); 770 } 771 772 public LiteralProcessor getLiteralProcessor() { 773 return literalProcessor; 774 } 775 776 public ASTPrinter getASTPrinter() { 777 return printer; 778 } 779 780 public ArrayList getParameters() { 781 return parameters; 782 } 783 784 public int getNumberOfParametersInSetClause() { 785 return numberOfParametersInSetClause; 786 } 787 788 protected void evaluateAssignment(AST eq) throws SemanticException { 789 Queryable persister = getCurrentFromClause().getFromElement().getQueryable(); 790 evaluateAssignment( eq, persister, -1 ); 791 } 792 793 private void evaluateAssignment(AST eq, Queryable persister, int targetIndex) { 794 if ( persister.isMultiTable() ) { 795 AssignmentSpecification specification = new AssignmentSpecification( eq, persister ); 797 if ( targetIndex >= 0 ) { 798 assignmentSpecifications.add( targetIndex, specification ); 799 } 800 else { 801 assignmentSpecifications.add( specification ); 802 } 803 numberOfParametersInSetClause += specification.getParameters().length; 804 } 805 } 806 807 public ArrayList getAssignmentSpecifications() { 808 return assignmentSpecifications; 809 } 810 811 protected AST createIntoClause(String path, AST propertySpec) throws SemanticException { 812 Queryable persister = ( Queryable ) getSessionFactoryHelper().requireClassPersister( path ); 813 814 IntoClause intoClause = ( IntoClause ) getASTFactory().create( INTO, persister.getEntityName() ); 815 intoClause.setFirstChild( propertySpec ); 816 intoClause.initialize( persister ); 817 818 addQuerySpaces( persister.getQuerySpaces() ); 819 820 return intoClause; 821 } 822 823 protected void prepareVersioned(AST updateNode, AST versioned) throws SemanticException { 824 UpdateStatement updateStatement = ( UpdateStatement ) updateNode; 825 FromClause fromClause = updateStatement.getFromClause(); 826 if ( versioned != null ) { 827 Queryable persister = fromClause.getFromElement().getQueryable(); 829 if ( !persister.isVersioned() ) { 830 throw new SemanticException( "increment option specified for update of non-versioned entity" ); 831 } 832 833 VersionType versionType = persister.getVersionType(); 834 if ( versionType instanceof UserVersionType ) { 835 throw new SemanticException( "user-defined version types not supported for increment option" ); 836 } 837 838 AST eq = getASTFactory().create( HqlSqlTokenTypes.EQ, "=" ); 839 AST versionPropertyNode = generateVersionPropertyNode( persister ); 840 841 eq.setFirstChild( versionPropertyNode ); 842 843 AST versionIncrementNode = null; 844 if ( Date .class.isAssignableFrom( versionType.getReturnedClass() ) ) { 845 versionIncrementNode = getASTFactory().create( HqlSqlTokenTypes.PARAM, "?" ); 846 ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification( versionType ); 847 ( ( ParameterNode ) versionIncrementNode ).setHqlParameterSpecification( paramSpec ); 848 parameters.add( 0, paramSpec ); 849 } 850 else { 851 versionIncrementNode = getASTFactory().create( HqlSqlTokenTypes.PLUS, "+" ); 854 versionIncrementNode.setFirstChild( generateVersionPropertyNode( persister ) ); 855 versionIncrementNode.addChild( getASTFactory().create( HqlSqlTokenTypes.IDENT, "1" ) ); 856 } 857 858 eq.addChild( versionIncrementNode ); 859 860 evaluateAssignment( eq, persister, 0 ); 861 862 AST setClause = updateStatement.getSetClause(); 863 AST currentFirstSetElement = setClause.getFirstChild(); 864 setClause.setFirstChild( eq ); 865 eq.setNextSibling( currentFirstSetElement ); 866 } 867 } 868 869 private AST generateVersionPropertyNode(Queryable persister) throws SemanticException { 870 String versionPropertyName = persister.getPropertyNames()[ persister.getVersionProperty() ]; 871 AST versionPropertyRef = getASTFactory().create( HqlSqlTokenTypes.IDENT, versionPropertyName ); 872 AST versionPropertyNode = lookupNonQualifiedProperty( versionPropertyRef ); 873 resolve( versionPropertyNode ); 874 return versionPropertyNode; 875 } 876 877 public static void panic() { 878 throw new QueryException( "TreeWalker: panic" ); 879 } 880 } 881 | Popular Tags |