Source Code Cross Referenced for HqlSqlWalker.java in  » Database-ORM » hibernate » org » hibernate » hql » ast » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » hibernate » org.hibernate.hql.ast 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // $Id: HqlSqlWalker.java 10946 2006-12-07 14:50:59Z steve.ebersole@jboss.com $
0002:        package org.hibernate.hql.ast;
0003:
0004:        import java.io.Serializable;
0005:        import java.util.ArrayList;
0006:        import java.util.Date;
0007:        import java.util.HashMap;
0008:        import java.util.HashSet;
0009:        import java.util.Iterator;
0010:        import java.util.List;
0011:        import java.util.Map;
0012:        import java.util.Set;
0013:
0014:        import org.apache.commons.logging.Log;
0015:        import org.apache.commons.logging.LogFactory;
0016:        import org.hibernate.QueryException;
0017:        import org.hibernate.HibernateException;
0018:        import org.hibernate.engine.JoinSequence;
0019:        import org.hibernate.engine.ParameterBinder;
0020:        import org.hibernate.engine.SessionFactoryImplementor;
0021:        import org.hibernate.hql.QueryTranslator;
0022:        import org.hibernate.hql.antlr.HqlSqlBaseWalker;
0023:        import org.hibernate.hql.antlr.HqlSqlTokenTypes;
0024:        import org.hibernate.hql.antlr.HqlTokenTypes;
0025:        import org.hibernate.hql.antlr.SqlTokenTypes;
0026:        import org.hibernate.hql.ast.tree.AssignmentSpecification;
0027:        import org.hibernate.hql.ast.tree.CollectionFunction;
0028:        import org.hibernate.hql.ast.tree.ConstructorNode;
0029:        import org.hibernate.hql.ast.tree.DeleteStatement;
0030:        import org.hibernate.hql.ast.tree.DotNode;
0031:        import org.hibernate.hql.ast.tree.FromClause;
0032:        import org.hibernate.hql.ast.tree.FromElement;
0033:        import org.hibernate.hql.ast.tree.FromReferenceNode;
0034:        import org.hibernate.hql.ast.tree.IdentNode;
0035:        import org.hibernate.hql.ast.tree.IndexNode;
0036:        import org.hibernate.hql.ast.tree.InsertStatement;
0037:        import org.hibernate.hql.ast.tree.IntoClause;
0038:        import org.hibernate.hql.ast.tree.MethodNode;
0039:        import org.hibernate.hql.ast.tree.ParameterNode;
0040:        import org.hibernate.hql.ast.tree.QueryNode;
0041:        import org.hibernate.hql.ast.tree.ResolvableNode;
0042:        import org.hibernate.hql.ast.tree.RestrictableStatement;
0043:        import org.hibernate.hql.ast.tree.SelectClause;
0044:        import org.hibernate.hql.ast.tree.SelectExpression;
0045:        import org.hibernate.hql.ast.tree.UpdateStatement;
0046:        import org.hibernate.hql.ast.tree.Node;
0047:        import org.hibernate.hql.ast.tree.OperatorNode;
0048:        import org.hibernate.hql.ast.util.ASTPrinter;
0049:        import org.hibernate.hql.ast.util.ASTUtil;
0050:        import org.hibernate.hql.ast.util.AliasGenerator;
0051:        import org.hibernate.hql.ast.util.JoinProcessor;
0052:        import org.hibernate.hql.ast.util.LiteralProcessor;
0053:        import org.hibernate.hql.ast.util.SessionFactoryHelper;
0054:        import org.hibernate.hql.ast.util.SyntheticAndFactory;
0055:        import org.hibernate.hql.ast.util.NodeTraverser;
0056:        import org.hibernate.id.IdentifierGenerator;
0057:        import org.hibernate.id.PostInsertIdentifierGenerator;
0058:        import org.hibernate.id.SequenceGenerator;
0059:        import org.hibernate.param.NamedParameterSpecification;
0060:        import org.hibernate.param.ParameterSpecification;
0061:        import org.hibernate.param.PositionalParameterSpecification;
0062:        import org.hibernate.param.VersionTypeSeedParameterSpecification;
0063:        import org.hibernate.param.CollectionFilterKeyParameterSpecification;
0064:        import org.hibernate.persister.collection.QueryableCollection;
0065:        import org.hibernate.persister.entity.Queryable;
0066:        import org.hibernate.sql.JoinFragment;
0067:        import org.hibernate.type.AssociationType;
0068:        import org.hibernate.type.Type;
0069:        import org.hibernate.type.VersionType;
0070:        import org.hibernate.type.DbTimestampType;
0071:        import org.hibernate.usertype.UserVersionType;
0072:        import org.hibernate.util.ArrayHelper;
0073:
0074:        import antlr.ASTFactory;
0075:        import antlr.RecognitionException;
0076:        import antlr.SemanticException;
0077:        import antlr.collections.AST;
0078:
0079:        /**
0080:         * Implements methods used by the HQL->SQL tree transform grammar (a.k.a. the second phase).
0081:         * <ul>
0082:         * <li>Isolates the Hibernate API-specific code from the ANTLR generated code.</li>
0083:         * <li>Handles the SQL framgents generated by the persisters in order to create the SELECT and FROM clauses,
0084:         * taking into account the joins and projections that are implied by the mappings (persister/queryable).</li>
0085:         * <li>Uses SqlASTFactory to create customized AST nodes.</li>
0086:         * </ul>
0087:         *
0088:         * @see SqlASTFactory
0089:         */
0090:        public class HqlSqlWalker extends HqlSqlBaseWalker implements 
0091:                ErrorReporter, ParameterBinder.NamedParameterSource {
0092:            private static final Log log = LogFactory
0093:                    .getLog(HqlSqlWalker.class);
0094:
0095:            private final QueryTranslatorImpl queryTranslatorImpl;
0096:            private final HqlParser hqlParser;
0097:            private final SessionFactoryHelper sessionFactoryHelper;
0098:            private final Map tokenReplacements;
0099:            private final AliasGenerator aliasGenerator = new AliasGenerator();
0100:            private final LiteralProcessor literalProcessor;
0101:            private final ParseErrorHandler parseErrorHandler;
0102:            private final ASTPrinter printer;
0103:            private final String collectionFilterRole;
0104:
0105:            private FromClause currentFromClause = null;
0106:            private SelectClause selectClause;
0107:
0108:            private Set querySpaces = new HashSet();
0109:
0110:            private int parameterCount;
0111:            private Map namedParameters = new HashMap();
0112:            private ArrayList parameters = new ArrayList();
0113:            private int numberOfParametersInSetClause;
0114:            private int positionalParameterCount;
0115:
0116:            private ArrayList assignmentSpecifications = new ArrayList();
0117:
0118:            private int impliedJoinType;
0119:
0120:            /**
0121:             * Create a new tree transformer.
0122:             *
0123:             * @param qti Back pointer to the query translator implementation that is using this tree transform.
0124:             * @param sfi The session factory implementor where the Hibernate mappings can be found.
0125:             * @param parser A reference to the phase-1 parser
0126:             * @param tokenReplacements Registers the token replacement map with the walker.  This map will
0127:             * be used to substitute function names and constants.
0128:             * @param collectionRole The collection role name of the collection used as the basis for the
0129:             * filter, NULL if this is not a collection filter compilation.
0130:             */
0131:            public HqlSqlWalker(QueryTranslatorImpl qti,
0132:                    SessionFactoryImplementor sfi, HqlParser parser,
0133:                    Map tokenReplacements, String collectionRole) {
0134:                setASTFactory(new SqlASTFactory(this ));
0135:                this .parseErrorHandler = new ErrorCounter();
0136:                this .queryTranslatorImpl = qti;
0137:                this .sessionFactoryHelper = new SessionFactoryHelper(sfi);
0138:                this .literalProcessor = new LiteralProcessor(this );
0139:                this .tokenReplacements = tokenReplacements;
0140:                this .hqlParser = parser;
0141:                this .printer = new ASTPrinter(SqlTokenTypes.class);
0142:                this .collectionFilterRole = collectionRole;
0143:            }
0144:
0145:            protected void prepareFromClauseInputTree(AST fromClauseInput) {
0146:                if (!isSubQuery()) {
0147:                    //			// inject param specifications to account for dynamic filter param values
0148:                    //			if ( ! getEnabledFilters().isEmpty() ) {
0149:                    //				Iterator filterItr = getEnabledFilters().values().iterator();
0150:                    //				while ( filterItr.hasNext() ) {
0151:                    //					FilterImpl filter = ( FilterImpl ) filterItr.next();
0152:                    //					if ( ! filter.getFilterDefinition().getParameterNames().isEmpty() ) {
0153:                    //						Iterator paramItr = filter.getFilterDefinition().getParameterNames().iterator();
0154:                    //						while ( paramItr.hasNext() ) {
0155:                    //							String parameterName = ( String ) paramItr.next();
0156:                    //							// currently param filters *only* work with single-column parameter types;
0157:                    //							// if that limitation is ever lifted, this logic will need to change to account for that
0158:                    //							ParameterNode collectionFilterKeyParameter = ( ParameterNode ) astFactory.create( PARAM, "?" );
0159:                    //							DynamicFilterParameterSpecification paramSpec = new DynamicFilterParameterSpecification(
0160:                    //									filter.getName(),
0161:                    //									parameterName,
0162:                    //									filter.getFilterDefinition().getParameterType( parameterName ),
0163:                    //									 positionalParameterCount++
0164:                    //							);
0165:                    //							collectionFilterKeyParameter.setHqlParameterSpecification( paramSpec );
0166:                    //							parameters.add( paramSpec );
0167:                    //						}
0168:                    //					}
0169:                    //				}
0170:                    //			}
0171:
0172:                    if (isFilter()) {
0173:                        // Handle collection-fiter compilation.
0174:                        // IMPORTANT NOTE: This is modifying the INPUT (HQL) tree, not the output tree!
0175:                        QueryableCollection persister = sessionFactoryHelper
0176:                                .getCollectionPersister(collectionFilterRole);
0177:                        Type collectionElementType = persister.getElementType();
0178:                        if (!collectionElementType.isEntityType()) {
0179:                            throw new QueryException(
0180:                                    "collection of values in filter: this");
0181:                        }
0182:
0183:                        String collectionElementEntityName = persister
0184:                                .getElementPersister().getEntityName();
0185:                        ASTFactory inputAstFactory = hqlParser.getASTFactory();
0186:                        AST fromElement = ASTUtil.create(inputAstFactory,
0187:                                HqlTokenTypes.FILTER_ENTITY,
0188:                                collectionElementEntityName);
0189:                        ASTUtil.createSibling(inputAstFactory,
0190:                                HqlTokenTypes.ALIAS, "this", fromElement);
0191:                        fromClauseInput.addChild(fromElement);
0192:                        // Show the modified AST.
0193:                        if (log.isDebugEnabled()) {
0194:                            log
0195:                                    .debug("prepareFromClauseInputTree() : Filter - Added 'this' as a from element...");
0196:                        }
0197:                        queryTranslatorImpl.showHqlAst(hqlParser.getAST());
0198:
0199:                        // Create a parameter specification for the collection filter...
0200:                        Type collectionFilterKeyType = sessionFactoryHelper
0201:                                .requireQueryableCollection(
0202:                                        collectionFilterRole).getKeyType();
0203:                        ParameterNode collectionFilterKeyParameter = (ParameterNode) astFactory
0204:                                .create(PARAM, "?");
0205:                        CollectionFilterKeyParameterSpecification collectionFilterKeyParameterSpec = new CollectionFilterKeyParameterSpecification(
0206:                                collectionFilterRole, collectionFilterKeyType,
0207:                                positionalParameterCount++);
0208:                        collectionFilterKeyParameter
0209:                                .setHqlParameterSpecification(collectionFilterKeyParameterSpec);
0210:                        parameters.add(collectionFilterKeyParameterSpec);
0211:                    }
0212:                }
0213:            }
0214:
0215:            public boolean isFilter() {
0216:                return collectionFilterRole != null;
0217:            }
0218:
0219:            public SessionFactoryHelper getSessionFactoryHelper() {
0220:                return sessionFactoryHelper;
0221:            }
0222:
0223:            public Map getTokenReplacements() {
0224:                return tokenReplacements;
0225:            }
0226:
0227:            public AliasGenerator getAliasGenerator() {
0228:                return aliasGenerator;
0229:            }
0230:
0231:            public FromClause getCurrentFromClause() {
0232:                return currentFromClause;
0233:            }
0234:
0235:            public ParseErrorHandler getParseErrorHandler() {
0236:                return parseErrorHandler;
0237:            }
0238:
0239:            public void reportError(RecognitionException e) {
0240:                parseErrorHandler.reportError(e); // Use the delegate.
0241:            }
0242:
0243:            public void reportError(String s) {
0244:                parseErrorHandler.reportError(s); // Use the delegate.
0245:            }
0246:
0247:            public void reportWarning(String s) {
0248:                parseErrorHandler.reportWarning(s);
0249:            }
0250:
0251:            /**
0252:             * Returns the set of unique query spaces (a.k.a.
0253:             * table names) that occurred in the query.
0254:             *
0255:             * @return A set of table names (Strings).
0256:             */
0257:            public Set getQuerySpaces() {
0258:                return querySpaces;
0259:            }
0260:
0261:            protected AST createFromElement(String path, AST alias,
0262:                    AST propertyFetch) throws SemanticException {
0263:                FromElement fromElement = currentFromClause.addFromElement(
0264:                        path, alias);
0265:                fromElement.setAllPropertyFetch(propertyFetch != null);
0266:                return fromElement;
0267:            }
0268:
0269:            protected AST createFromFilterElement(AST filterEntity, AST alias)
0270:                    throws SemanticException {
0271:                FromElement fromElement = currentFromClause.addFromElement(
0272:                        filterEntity.getText(), alias);
0273:                FromClause fromClause = fromElement.getFromClause();
0274:                QueryableCollection persister = sessionFactoryHelper
0275:                        .getCollectionPersister(collectionFilterRole);
0276:                // Get the names of the columns used to link between the collection
0277:                // owner and the collection elements.
0278:                String[] keyColumnNames = persister.getKeyColumnNames();
0279:                String fkTableAlias = persister.isOneToMany() ? fromElement
0280:                        .getTableAlias() : fromClause.getAliasGenerator()
0281:                        .createName(collectionFilterRole);
0282:                JoinSequence join = sessionFactoryHelper.createJoinSequence();
0283:                join.setRoot(persister, fkTableAlias);
0284:                if (!persister.isOneToMany()) {
0285:                    join.addJoin((AssociationType) persister.getElementType(),
0286:                            fromElement.getTableAlias(),
0287:                            JoinFragment.INNER_JOIN, persister
0288:                                    .getElementColumnNames(fkTableAlias));
0289:                }
0290:                join.addCondition(fkTableAlias, keyColumnNames, " = ?");
0291:                fromElement.setJoinSequence(join);
0292:                fromElement.setFilter(true);
0293:                if (log.isDebugEnabled()) {
0294:                    log
0295:                            .debug("createFromFilterElement() : processed filter FROM element.");
0296:                }
0297:                return fromElement;
0298:            }
0299:
0300:            protected void createFromJoinElement(AST path, AST alias,
0301:                    int joinType, AST fetchNode, AST propertyFetch, AST with)
0302:                    throws SemanticException {
0303:                boolean fetch = fetchNode != null;
0304:                if (fetch && isSubQuery()) {
0305:                    throw new QueryException(
0306:                            "fetch not allowed in subquery from-elements");
0307:                }
0308:                // The path AST should be a DotNode, and it should have been evaluated already.
0309:                if (path.getType() != SqlTokenTypes.DOT) {
0310:                    throw new SemanticException("Path expected for join!");
0311:                }
0312:                DotNode dot = (DotNode) path;
0313:                int hibernateJoinType = JoinProcessor
0314:                        .toHibernateJoinType(joinType);
0315:                dot.setJoinType(hibernateJoinType); // Tell the dot node about the join type.
0316:                dot.setFetch(fetch);
0317:                // Generate an explicit join for the root dot node.   The implied joins will be collected and passed up
0318:                // to the root dot node.
0319:                dot
0320:                        .resolve(true, false, alias == null ? null : alias
0321:                                .getText());
0322:                FromElement fromElement = dot.getImpliedJoin();
0323:                fromElement.setAllPropertyFetch(propertyFetch != null);
0324:
0325:                if (with != null) {
0326:                    if (fetch) {
0327:                        throw new SemanticException(
0328:                                "with-clause not allowed on fetched associations; use filters");
0329:                    }
0330:                    handleWithFragment(fromElement, with);
0331:                }
0332:
0333:                if (log.isDebugEnabled()) {
0334:                    log.debug("createFromJoinElement() : "
0335:                            + getASTPrinter().showAsString(fromElement,
0336:                                    "-- join tree --"));
0337:                }
0338:            }
0339:
0340:            private void handleWithFragment(FromElement fromElement,
0341:                    AST hqlWithNode) throws SemanticException {
0342:                try {
0343:                    withClause(hqlWithNode);
0344:                    AST hqlSqlWithNode = returnAST;
0345:                    if (log.isDebugEnabled()) {
0346:                        log.debug("handleWithFragment() : "
0347:                                + getASTPrinter().showAsString(hqlSqlWithNode,
0348:                                        "-- with clause --"));
0349:                    }
0350:                    WithClauseVisitor visitor = new WithClauseVisitor();
0351:                    NodeTraverser traverser = new NodeTraverser(visitor);
0352:                    traverser.traverseDepthFirst(hqlSqlWithNode);
0353:                    FromElement referencedFromElement = visitor
0354:                            .getReferencedFromElement();
0355:                    if (referencedFromElement != fromElement) {
0356:                        throw new InvalidWithClauseException(
0357:                                "with-clause expressions did not reference from-clause element to which the with-clause was associated");
0358:                    }
0359:                    SqlGenerator sql = new SqlGenerator(
0360:                            getSessionFactoryHelper().getFactory());
0361:                    sql.whereExpr(hqlSqlWithNode.getFirstChild());
0362:                    fromElement.setWithClauseFragment(visitor.getJoinAlias(),
0363:                            "(" + sql.getSQL() + ")");
0364:
0365:                } catch (SemanticException e) {
0366:                    throw e;
0367:                } catch (InvalidWithClauseException e) {
0368:                    throw e;
0369:                } catch (Exception e) {
0370:                    throw new SemanticException(e.getMessage());
0371:                }
0372:            }
0373:
0374:            private static class WithClauseVisitor implements 
0375:                    NodeTraverser.VisitationStrategy {
0376:                private FromElement referencedFromElement;
0377:                private String joinAlias;
0378:
0379:                public void visit(AST node) {
0380:                    // todo : currently expects that the individual with expressions apply to the same sql table join.
0381:                    //      This may not be the case for joined-subclass where the property values
0382:                    //      might be coming from different tables in the joined hierarchy.  At some
0383:                    //      point we should expand this to support that capability.  However, that has
0384:                    //      some difficulties:
0385:                    //          1) the biggest is how to handle ORs when the individual comparisons are
0386:                    //              linked to different sql joins.
0387:                    //          2) here we would need to track each comparison individually, along with
0388:                    //              the join alias to which it applies and then pass that information
0389:                    //              back to the FromElement so it can pass it along to the JoinSequence
0390:
0391:                    if (node instanceof  DotNode) {
0392:                        DotNode dotNode = (DotNode) node;
0393:                        FromElement fromElement = dotNode.getFromElement();
0394:                        if (referencedFromElement != null) {
0395:                            if (fromElement != referencedFromElement) {
0396:                                throw new HibernateException(
0397:                                        "with-clause referenced two different from-clause elements");
0398:                            }
0399:                        } else {
0400:                            referencedFromElement = fromElement;
0401:                            joinAlias = extractAppliedAlias(dotNode);
0402:                            // todo : temporary
0403:                            //      needed because currently persister is the one that
0404:                            //      creates and renders the join fragments for inheritence
0405:                            //      hierarchies...
0406:                            if (!joinAlias.equals(referencedFromElement
0407:                                    .getTableAlias())) {
0408:                                throw new InvalidWithClauseException(
0409:                                        "with clause can only reference columns in the driving table");
0410:                            }
0411:                        }
0412:                    }
0413:                }
0414:
0415:                private String extractAppliedAlias(DotNode dotNode) {
0416:                    return dotNode.getText().substring(0,
0417:                            dotNode.getText().indexOf('.'));
0418:                }
0419:
0420:                public FromElement getReferencedFromElement() {
0421:                    return referencedFromElement;
0422:                }
0423:
0424:                public String getJoinAlias() {
0425:                    return joinAlias;
0426:                }
0427:            }
0428:
0429:            /**
0430:             * Sets the current 'FROM' context.
0431:             *
0432:             * @param fromNode      The new 'FROM' context.
0433:             * @param inputFromNode The from node from the input AST.
0434:             */
0435:            protected void pushFromClause(AST fromNode, AST inputFromNode) {
0436:                FromClause newFromClause = (FromClause) fromNode;
0437:                newFromClause.setParentFromClause(currentFromClause);
0438:                currentFromClause = newFromClause;
0439:            }
0440:
0441:            /**
0442:             * Returns to the previous 'FROM' context.
0443:             */
0444:            private void popFromClause() {
0445:                currentFromClause = currentFromClause.getParentFromClause();
0446:            }
0447:
0448:            protected void lookupAlias(AST aliasRef) throws SemanticException {
0449:                FromElement alias = currentFromClause.getFromElement(aliasRef
0450:                        .getText());
0451:                FromReferenceNode aliasRefNode = (FromReferenceNode) aliasRef;
0452:                aliasRefNode.setFromElement(alias);
0453:            }
0454:
0455:            protected void setImpliedJoinType(int joinType) {
0456:                impliedJoinType = JoinProcessor.toHibernateJoinType(joinType);
0457:            }
0458:
0459:            public int getImpliedJoinType() {
0460:                return impliedJoinType;
0461:            }
0462:
0463:            protected AST lookupProperty(AST dot, boolean root, boolean inSelect)
0464:                    throws SemanticException {
0465:                DotNode dotNode = (DotNode) dot;
0466:                FromReferenceNode lhs = dotNode.getLhs();
0467:                AST rhs = lhs.getNextSibling();
0468:                switch (rhs.getType()) {
0469:                case SqlTokenTypes.ELEMENTS:
0470:                case SqlTokenTypes.INDICES:
0471:                    if (log.isDebugEnabled()) {
0472:                        log.debug("lookupProperty() " + dotNode.getPath()
0473:                                + " => " + rhs.getText() + "(" + lhs.getPath()
0474:                                + ")");
0475:                    }
0476:                    CollectionFunction f = (CollectionFunction) rhs;
0477:                    // Re-arrange the tree so that the collection function is the root and the lhs is the path.
0478:                    f.setFirstChild(lhs);
0479:                    lhs.setNextSibling(null);
0480:                    dotNode.setFirstChild(f);
0481:                    resolve(lhs); // Don't forget to resolve the argument!
0482:                    f.resolve(inSelect); // Resolve the collection function now.
0483:                    return f;
0484:                default:
0485:                    // Resolve everything up to this dot, but don't resolve the placeholders yet.
0486:                    dotNode.resolveFirstChild();
0487:                    return dotNode;
0488:                }
0489:            }
0490:
0491:            protected boolean isNonQualifiedPropertyRef(AST ident) {
0492:                final String identText = ident.getText();
0493:                if (currentFromClause.isFromElementAlias(identText)) {
0494:                    return false;
0495:                }
0496:
0497:                List fromElements = currentFromClause.getExplicitFromElements();
0498:                if (fromElements.size() == 1) {
0499:                    final FromElement fromElement = (FromElement) fromElements
0500:                            .get(0);
0501:                    try {
0502:                        log.trace("attempting to resolve property ["
0503:                                + identText + "] as a non-qualified ref");
0504:                        return fromElement.getPropertyMapping(identText)
0505:                                .toType(identText) != null;
0506:                    } catch (QueryException e) {
0507:                        // Should mean that no such property was found
0508:                    }
0509:                }
0510:
0511:                return false;
0512:            }
0513:
0514:            protected AST lookupNonQualifiedProperty(AST property)
0515:                    throws SemanticException {
0516:                final FromElement fromElement = (FromElement) currentFromClause
0517:                        .getExplicitFromElements().get(0);
0518:                AST syntheticDotNode = generateSyntheticDotNodeForNonQualifiedPropertyRef(
0519:                        property, fromElement);
0520:                return lookupProperty(syntheticDotNode, false,
0521:                        getCurrentClauseType() == HqlSqlTokenTypes.SELECT);
0522:            }
0523:
0524:            private AST generateSyntheticDotNodeForNonQualifiedPropertyRef(
0525:                    AST property, FromElement fromElement) {
0526:                AST dot = getASTFactory().create(DOT,
0527:                        "{non-qualified-property-ref}");
0528:                // TODO : better way?!?
0529:                ((DotNode) dot).setPropertyPath(((FromReferenceNode) property)
0530:                        .getPath());
0531:
0532:                IdentNode syntheticAlias = (IdentNode) getASTFactory().create(
0533:                        IDENT, "{synthetic-alias}");
0534:                syntheticAlias.setFromElement(fromElement);
0535:                syntheticAlias.setResolved();
0536:
0537:                dot.setFirstChild(syntheticAlias);
0538:                dot.addChild(property);
0539:
0540:                return dot;
0541:            }
0542:
0543:            protected void processQuery(AST select, AST query)
0544:                    throws SemanticException {
0545:                if (log.isDebugEnabled()) {
0546:                    log.debug("processQuery() : " + query.toStringTree());
0547:                }
0548:
0549:                try {
0550:                    QueryNode qn = (QueryNode) query;
0551:
0552:                    // Was there an explicit select expression?
0553:                    boolean explicitSelect = select != null
0554:                            && select.getNumberOfChildren() > 0;
0555:
0556:                    if (!explicitSelect) {
0557:                        // No explicit select expression; render the id and properties
0558:                        // projection lists for every persister in the from clause into
0559:                        // a single 'token node'.
0560:                        //TODO: the only reason we need this stuff now is collection filters,
0561:                        //      we should get rid of derived select clause completely!
0562:                        createSelectClauseFromFromClause(qn);
0563:                    } else {
0564:                        // Use the explicitly declared select expression; determine the
0565:                        // return types indicated by each select token
0566:                        useSelectClause(select);
0567:                    }
0568:
0569:                    // After that, process the JOINs.
0570:                    // Invoke a delegate to do the work, as this is farily complex.
0571:                    JoinProcessor joinProcessor = new JoinProcessor(astFactory,
0572:                            queryTranslatorImpl);
0573:                    joinProcessor.processJoins(qn, isSubQuery());
0574:
0575:                    // Attach any mapping-defined "ORDER BY" fragments
0576:                    Iterator itr = qn.getFromClause().getProjectionList()
0577:                            .iterator();
0578:                    while (itr.hasNext()) {
0579:                        final FromElement fromElement = (FromElement) itr
0580:                                .next();
0581:                        //			if ( fromElement.isFetch() && fromElement.isCollectionJoin() ) {
0582:                        if (fromElement.isFetch()
0583:                                && fromElement.getQueryableCollection() != null) {
0584:                            // Does the collection referenced by this FromElement
0585:                            // specify an order-by attribute?  If so, attach it to
0586:                            // the query's order-by
0587:                            if (fromElement.getQueryableCollection()
0588:                                    .hasOrdering()) {
0589:                                String orderByFragment = fromElement
0590:                                        .getQueryableCollection()
0591:                                        .getSQLOrderByString(
0592:                                                fromElement
0593:                                                        .getCollectionTableAlias());
0594:                                qn.getOrderByClause().addOrderFragment(
0595:                                        orderByFragment);
0596:                            }
0597:                            if (fromElement.getQueryableCollection()
0598:                                    .hasManyToManyOrdering()) {
0599:                                String orderByFragment = fromElement
0600:                                        .getQueryableCollection()
0601:                                        .getManyToManyOrderByString(
0602:                                                fromElement.getTableAlias());
0603:                                qn.getOrderByClause().addOrderFragment(
0604:                                        orderByFragment);
0605:                            }
0606:                        }
0607:                    }
0608:                } finally {
0609:                    popFromClause();
0610:                }
0611:            }
0612:
0613:            protected void postProcessDML(RestrictableStatement statement)
0614:                    throws SemanticException {
0615:                statement.getFromClause().resolve();
0616:
0617:                FromElement fromElement = (FromElement) statement
0618:                        .getFromClause().getFromElements().get(0);
0619:                Queryable persister = fromElement.getQueryable();
0620:                // Make #@%$^#^&# sure no alias is applied to the table name
0621:                fromElement.setText(persister.getTableName());
0622:
0623:                // append any filter fragments; the EMPTY_MAP is used under the assumption that
0624:                // currently enabled filters should not affect this process
0625:                if (persister.getDiscriminatorType() != null) {
0626:                    new SyntheticAndFactory(getASTFactory())
0627:                            .addDiscriminatorWhereFragment(statement,
0628:                                    persister, java.util.Collections.EMPTY_MAP,
0629:                                    fromElement.getTableAlias());
0630:                }
0631:
0632:            }
0633:
0634:            protected void postProcessUpdate(AST update)
0635:                    throws SemanticException {
0636:                UpdateStatement updateStatement = (UpdateStatement) update;
0637:
0638:                postProcessDML(updateStatement);
0639:            }
0640:
0641:            protected void postProcessDelete(AST delete)
0642:                    throws SemanticException {
0643:                postProcessDML((DeleteStatement) delete);
0644:            }
0645:
0646:            public static boolean supportsIdGenWithBulkInsertion(
0647:                    IdentifierGenerator generator) {
0648:                return SequenceGenerator.class.isAssignableFrom(generator
0649:                        .getClass())
0650:                        || PostInsertIdentifierGenerator.class
0651:                                .isAssignableFrom(generator.getClass());
0652:            }
0653:
0654:            protected void postProcessInsert(AST insert)
0655:                    throws SemanticException, QueryException {
0656:                InsertStatement insertStatement = (InsertStatement) insert;
0657:                insertStatement.validate();
0658:
0659:                SelectClause selectClause = insertStatement.getSelectClause();
0660:                Queryable persister = insertStatement.getIntoClause()
0661:                        .getQueryable();
0662:
0663:                if (!insertStatement.getIntoClause().isExplicitIdInsertion()) {
0664:                    // We need to generate ids as part of this bulk insert.
0665:                    //
0666:                    // Note that this is only supported for sequence-style generators and
0667:                    // post-insert-style generators; basically, only in-db generators
0668:                    IdentifierGenerator generator = persister
0669:                            .getIdentifierGenerator();
0670:                    if (!supportsIdGenWithBulkInsertion(generator)) {
0671:                        throw new QueryException(
0672:                                "can only generate ids as part of bulk insert with either sequence or post-insert style generators");
0673:                    }
0674:
0675:                    AST idSelectExprNode = null;
0676:
0677:                    if (SequenceGenerator.class.isAssignableFrom(generator
0678:                            .getClass())) {
0679:                        String seqName = (String) ((SequenceGenerator) generator)
0680:                                .generatorKey();
0681:                        String nextval = sessionFactoryHelper.getFactory()
0682:                                .getDialect().getSelectSequenceNextValString(
0683:                                        seqName);
0684:                        idSelectExprNode = getASTFactory().create(
0685:                                HqlSqlTokenTypes.SQL_TOKEN, nextval);
0686:                    } else {
0687:                        //Don't need this, because we should never ever be selecting no columns in an insert ... select...
0688:                        //and because it causes a bug on DB2
0689:                        /*String idInsertString = sessionFactoryHelper.getFactory().getDialect().getIdentityInsertString();
0690:                        if ( idInsertString != null ) {
0691:                        	idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, idInsertString );
0692:                        }*/
0693:                    }
0694:
0695:                    if (idSelectExprNode != null) {
0696:                        AST currentFirstSelectExprNode = selectClause
0697:                                .getFirstChild();
0698:                        selectClause.setFirstChild(idSelectExprNode);
0699:                        idSelectExprNode
0700:                                .setNextSibling(currentFirstSelectExprNode);
0701:
0702:                        insertStatement.getIntoClause().prependIdColumnSpec();
0703:                    }
0704:                }
0705:
0706:                final boolean includeVersionProperty = persister.isVersioned()
0707:                        && !insertStatement.getIntoClause()
0708:                                .isExplicitVersionInsertion()
0709:                        && persister.isVersionPropertyInsertable();
0710:                if (includeVersionProperty) {
0711:                    // We need to seed the version value as part of this bulk insert
0712:                    VersionType versionType = persister.getVersionType();
0713:                    AST versionValueNode = null;
0714:
0715:                    if (sessionFactoryHelper.getFactory().getDialect()
0716:                            .supportsParametersInInsertSelect()) {
0717:                        versionValueNode = getASTFactory().create(
0718:                                HqlSqlTokenTypes.PARAM, "?");
0719:                        ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(
0720:                                versionType);
0721:                        ((ParameterNode) versionValueNode)
0722:                                .setHqlParameterSpecification(paramSpec);
0723:                        parameters.add(0, paramSpec);
0724:                    } else {
0725:                        if (isIntegral(versionType)) {
0726:                            try {
0727:                                Object seedValue = versionType.seed(null);
0728:                                versionValueNode = getASTFactory().create(
0729:                                        HqlSqlTokenTypes.SQL_TOKEN,
0730:                                        seedValue.toString());
0731:                            } catch (Throwable t) {
0732:                                throw new QueryException(
0733:                                        "could not determine seed value for version on bulk insert ["
0734:                                                + versionType + "]");
0735:                            }
0736:                        } else if (isDatabaseGeneratedTimestamp(versionType)) {
0737:                            String functionName = sessionFactoryHelper
0738:                                    .getFactory().getDialect()
0739:                                    .getCurrentTimestampSQLFunctionName();
0740:                            versionValueNode = getASTFactory().create(
0741:                                    HqlSqlTokenTypes.SQL_TOKEN, functionName);
0742:                        } else {
0743:                            throw new QueryException(
0744:                                    "cannot handle version type ["
0745:                                            + versionType
0746:                                            + "] on bulk inserts with dialects not supporting parameters in insert-select statements");
0747:                        }
0748:                    }
0749:
0750:                    AST currentFirstSelectExprNode = selectClause
0751:                            .getFirstChild();
0752:                    selectClause.setFirstChild(versionValueNode);
0753:                    versionValueNode.setNextSibling(currentFirstSelectExprNode);
0754:
0755:                    insertStatement.getIntoClause().prependVersionColumnSpec();
0756:                }
0757:
0758:                if (insertStatement.getIntoClause().isDiscriminated()) {
0759:                    String sqlValue = insertStatement.getIntoClause()
0760:                            .getQueryable().getDiscriminatorSQLValue();
0761:                    AST discrimValue = getASTFactory().create(
0762:                            HqlSqlTokenTypes.SQL_TOKEN, sqlValue);
0763:                    insertStatement.getSelectClause().addChild(discrimValue);
0764:                }
0765:
0766:            }
0767:
0768:            private boolean isDatabaseGeneratedTimestamp(Type type) {
0769:                // currently only the Hibernate-supplied DbTimestampType is supported here
0770:                return DbTimestampType.class.isAssignableFrom(type.getClass());
0771:            }
0772:
0773:            private boolean isIntegral(Type type) {
0774:                return Long.class.isAssignableFrom(type.getReturnedClass())
0775:                        || Integer.class.isAssignableFrom(type
0776:                                .getReturnedClass())
0777:                        || long.class.isAssignableFrom(type.getReturnedClass())
0778:                        || int.class.isAssignableFrom(type.getReturnedClass());
0779:            }
0780:
0781:            private void useSelectClause(AST select) throws SemanticException {
0782:                selectClause = (SelectClause) select;
0783:                selectClause.initializeExplicitSelectClause(currentFromClause);
0784:            }
0785:
0786:            private void createSelectClauseFromFromClause(QueryNode qn)
0787:                    throws SemanticException {
0788:                AST select = astFactory.create(SELECT_CLAUSE,
0789:                        "{derived select clause}");
0790:                AST sibling = qn.getFromClause();
0791:                qn.setFirstChild(select);
0792:                select.setNextSibling(sibling);
0793:                selectClause = (SelectClause) select;
0794:                selectClause.initializeDerivedSelectClause(currentFromClause);
0795:                if (log.isDebugEnabled()) {
0796:                    log.debug("Derived SELECT clause created.");
0797:                }
0798:            }
0799:
0800:            protected void resolve(AST node) throws SemanticException {
0801:                if (node != null) {
0802:                    // This is called when it's time to fully resolve a path expression.
0803:                    ResolvableNode r = (ResolvableNode) node;
0804:                    if (isInFunctionCall()) {
0805:                        r.resolveInFunctionCall(false, true);
0806:                    } else {
0807:                        r.resolve(false, true); // Generate implicit joins, only if necessary.
0808:                    }
0809:                }
0810:            }
0811:
0812:            protected void resolveSelectExpression(AST node)
0813:                    throws SemanticException {
0814:                // This is called when it's time to fully resolve a path expression.
0815:                int type = node.getType();
0816:                switch (type) {
0817:                case DOT:
0818:                    DotNode dot = (DotNode) node;
0819:                    dot.resolveSelectExpression();
0820:                    break;
0821:                case ALIAS_REF:
0822:                    // Notify the FROM element that it is being referenced by the select.
0823:                    FromReferenceNode aliasRefNode = (FromReferenceNode) node;
0824:                    //aliasRefNode.resolve( false, false, aliasRefNode.getText() ); //TODO: is it kosher to do it here?
0825:                    aliasRefNode.resolve(false, false); //TODO: is it kosher to do it here?
0826:                    FromElement fromElement = aliasRefNode.getFromElement();
0827:                    if (fromElement != null) {
0828:                        fromElement.setIncludeSubclasses(true);
0829:                    }
0830:                default:
0831:                    break;
0832:                }
0833:            }
0834:
0835:            protected void beforeSelectClause() throws SemanticException {
0836:                // Turn off includeSubclasses on all FromElements.
0837:                FromClause from = getCurrentFromClause();
0838:                List fromElements = from.getFromElements();
0839:                for (Iterator iterator = fromElements.iterator(); iterator
0840:                        .hasNext();) {
0841:                    FromElement fromElement = (FromElement) iterator.next();
0842:                    fromElement.setIncludeSubclasses(false);
0843:                }
0844:            }
0845:
0846:            protected AST generatePositionalParameter(AST inputNode)
0847:                    throws SemanticException {
0848:                if (namedParameters.size() > 0) {
0849:                    throw new SemanticException(
0850:                            "cannot define positional parameter after any named parameters have been defined");
0851:                }
0852:                ParameterNode parameter = (ParameterNode) astFactory.create(
0853:                        PARAM, "?");
0854:                PositionalParameterSpecification paramSpec = new PositionalParameterSpecification(
0855:                        ((Node) inputNode).getLine(), ((Node) inputNode)
0856:                                .getColumn(), positionalParameterCount++);
0857:                parameter.setHqlParameterSpecification(paramSpec);
0858:                parameters.add(paramSpec);
0859:                return parameter;
0860:            }
0861:
0862:            protected AST generateNamedParameter(AST delimiterNode, AST nameNode)
0863:                    throws SemanticException {
0864:                String name = nameNode.getText();
0865:                trackNamedParameterPositions(name);
0866:
0867:                // create the node initially with the param name so that it shows
0868:                // appropriately in the "original text" attribute
0869:                ParameterNode parameter = (ParameterNode) astFactory.create(
0870:                        NAMED_PARAM, name);
0871:                parameter.setText("?");
0872:
0873:                NamedParameterSpecification paramSpec = new NamedParameterSpecification(
0874:                        ((Node) delimiterNode).getLine(),
0875:                        ((Node) delimiterNode).getColumn(), name);
0876:                parameter.setHqlParameterSpecification(paramSpec);
0877:                parameters.add(paramSpec);
0878:                return parameter;
0879:            }
0880:
0881:            private void trackNamedParameterPositions(String name) {
0882:                Integer loc = new Integer(parameterCount++);
0883:                Object o = namedParameters.get(name);
0884:                if (o == null) {
0885:                    namedParameters.put(name, loc);
0886:                } else if (o instanceof  Integer) {
0887:                    ArrayList list = new ArrayList(4);
0888:                    list.add(o);
0889:                    list.add(loc);
0890:                    namedParameters.put(name, list);
0891:                } else {
0892:                    ((ArrayList) o).add(loc);
0893:                }
0894:            }
0895:
0896:            protected void processConstant(AST constant)
0897:                    throws SemanticException {
0898:                literalProcessor.processConstant(constant, true); // Use the delegate, resolve identifiers as FROM element aliases.
0899:            }
0900:
0901:            protected void processBoolean(AST constant)
0902:                    throws SemanticException {
0903:                literalProcessor.processBoolean(constant); // Use the delegate.
0904:            }
0905:
0906:            protected void processNumericLiteral(AST literal) {
0907:                literalProcessor.processNumeric(literal);
0908:            }
0909:
0910:            protected void processIndex(AST indexOp) throws SemanticException {
0911:                IndexNode indexNode = (IndexNode) indexOp;
0912:                indexNode.resolve(true, true);
0913:            }
0914:
0915:            protected void processFunction(AST functionCall, boolean inSelect)
0916:                    throws SemanticException {
0917:                MethodNode methodNode = (MethodNode) functionCall;
0918:                methodNode.resolve(inSelect);
0919:            }
0920:
0921:            protected void processConstructor(AST constructor)
0922:                    throws SemanticException {
0923:                ConstructorNode constructorNode = (ConstructorNode) constructor;
0924:                constructorNode.prepare();
0925:            }
0926:
0927:            protected void setAlias(AST selectExpr, AST ident) {
0928:                ((SelectExpression) selectExpr).setAlias(ident.getText());
0929:            }
0930:
0931:            /**
0932:             * Returns the locations of all occurrences of the named parameter.
0933:             */
0934:            public int[] getNamedParameterLocations(String name)
0935:                    throws QueryException {
0936:                Object o = namedParameters.get(name);
0937:                if (o == null) {
0938:                    QueryException qe = new QueryException(
0939:                            QueryTranslator.ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR
0940:                                    + name);
0941:                    qe.setQueryString(queryTranslatorImpl.getQueryString());
0942:                    throw qe;
0943:                }
0944:                if (o instanceof  Integer) {
0945:                    return new int[] { ((Integer) o).intValue() };
0946:                } else {
0947:                    return ArrayHelper.toIntArray((ArrayList) o);
0948:                }
0949:            }
0950:
0951:            public void addQuerySpaces(Serializable[] spaces) {
0952:                for (int i = 0; i < spaces.length; i++) {
0953:                    querySpaces.add(spaces[i]);
0954:                }
0955:            }
0956:
0957:            public Type[] getReturnTypes() {
0958:                return selectClause.getQueryReturnTypes();
0959:            }
0960:
0961:            public String[] getReturnAliases() {
0962:                return selectClause.getQueryReturnAliases();
0963:            }
0964:
0965:            public SelectClause getSelectClause() {
0966:                return selectClause;
0967:            }
0968:
0969:            public FromClause getFinalFromClause() {
0970:                FromClause top = currentFromClause;
0971:                while (top.getParentFromClause() != null) {
0972:                    top = top.getParentFromClause();
0973:                }
0974:                return top;
0975:            }
0976:
0977:            public boolean isShallowQuery() {
0978:                // select clauses for insert statements should alwasy be treated as shallow
0979:                return getStatementType() == INSERT
0980:                        || queryTranslatorImpl.isShallowQuery();
0981:            }
0982:
0983:            public Map getEnabledFilters() {
0984:                return queryTranslatorImpl.getEnabledFilters();
0985:            }
0986:
0987:            public LiteralProcessor getLiteralProcessor() {
0988:                return literalProcessor;
0989:            }
0990:
0991:            public ASTPrinter getASTPrinter() {
0992:                return printer;
0993:            }
0994:
0995:            public ArrayList getParameters() {
0996:                return parameters;
0997:            }
0998:
0999:            public int getNumberOfParametersInSetClause() {
1000:                return numberOfParametersInSetClause;
1001:            }
1002:
1003:            protected void evaluateAssignment(AST eq) throws SemanticException {
1004:                prepareLogicOperator(eq);
1005:                Queryable persister = getCurrentFromClause().getFromElement()
1006:                        .getQueryable();
1007:                evaluateAssignment(eq, persister, -1);
1008:            }
1009:
1010:            private void evaluateAssignment(AST eq, Queryable persister,
1011:                    int targetIndex) {
1012:                if (persister.isMultiTable()) {
1013:                    // no need to even collect this information if the persister is considered multi-table
1014:                    AssignmentSpecification specification = new AssignmentSpecification(
1015:                            eq, persister);
1016:                    if (targetIndex >= 0) {
1017:                        assignmentSpecifications
1018:                                .add(targetIndex, specification);
1019:                    } else {
1020:                        assignmentSpecifications.add(specification);
1021:                    }
1022:                    numberOfParametersInSetClause += specification
1023:                            .getParameters().length;
1024:                }
1025:            }
1026:
1027:            public ArrayList getAssignmentSpecifications() {
1028:                return assignmentSpecifications;
1029:            }
1030:
1031:            protected AST createIntoClause(String path, AST propertySpec)
1032:                    throws SemanticException {
1033:                Queryable persister = (Queryable) getSessionFactoryHelper()
1034:                        .requireClassPersister(path);
1035:
1036:                IntoClause intoClause = (IntoClause) getASTFactory().create(
1037:                        INTO, persister.getEntityName());
1038:                intoClause.setFirstChild(propertySpec);
1039:                intoClause.initialize(persister);
1040:
1041:                addQuerySpaces(persister.getQuerySpaces());
1042:
1043:                return intoClause;
1044:            }
1045:
1046:            protected void prepareVersioned(AST updateNode, AST versioned)
1047:                    throws SemanticException {
1048:                UpdateStatement updateStatement = (UpdateStatement) updateNode;
1049:                FromClause fromClause = updateStatement.getFromClause();
1050:                if (versioned != null) {
1051:                    // Make sure that the persister is versioned
1052:                    Queryable persister = fromClause.getFromElement()
1053:                            .getQueryable();
1054:                    if (!persister.isVersioned()) {
1055:                        throw new SemanticException(
1056:                                "increment option specified for update of non-versioned entity");
1057:                    }
1058:
1059:                    VersionType versionType = persister.getVersionType();
1060:                    if (versionType instanceof  UserVersionType) {
1061:                        throw new SemanticException(
1062:                                "user-defined version types not supported for increment option");
1063:                    }
1064:
1065:                    AST eq = getASTFactory().create(HqlSqlTokenTypes.EQ, "=");
1066:                    AST versionPropertyNode = generateVersionPropertyNode(persister);
1067:
1068:                    eq.setFirstChild(versionPropertyNode);
1069:
1070:                    AST versionIncrementNode = null;
1071:                    if (Date.class.isAssignableFrom(versionType
1072:                            .getReturnedClass())) {
1073:                        versionIncrementNode = getASTFactory().create(
1074:                                HqlSqlTokenTypes.PARAM, "?");
1075:                        ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(
1076:                                versionType);
1077:                        ((ParameterNode) versionIncrementNode)
1078:                                .setHqlParameterSpecification(paramSpec);
1079:                        parameters.add(0, paramSpec);
1080:                    } else {
1081:                        // Not possible to simply re-use the versionPropertyNode here as it causes
1082:                        // OOM errors due to circularity :(
1083:                        versionIncrementNode = getASTFactory().create(
1084:                                HqlSqlTokenTypes.PLUS, "+");
1085:                        versionIncrementNode
1086:                                .setFirstChild(generateVersionPropertyNode(persister));
1087:                        versionIncrementNode.addChild(getASTFactory().create(
1088:                                HqlSqlTokenTypes.IDENT, "1"));
1089:                    }
1090:
1091:                    eq.addChild(versionIncrementNode);
1092:
1093:                    evaluateAssignment(eq, persister, 0);
1094:
1095:                    AST setClause = updateStatement.getSetClause();
1096:                    AST currentFirstSetElement = setClause.getFirstChild();
1097:                    setClause.setFirstChild(eq);
1098:                    eq.setNextSibling(currentFirstSetElement);
1099:                }
1100:            }
1101:
1102:            private AST generateVersionPropertyNode(Queryable persister)
1103:                    throws SemanticException {
1104:                String versionPropertyName = persister.getPropertyNames()[persister
1105:                        .getVersionProperty()];
1106:                AST versionPropertyRef = getASTFactory().create(
1107:                        HqlSqlTokenTypes.IDENT, versionPropertyName);
1108:                AST versionPropertyNode = lookupNonQualifiedProperty(versionPropertyRef);
1109:                resolve(versionPropertyNode);
1110:                return versionPropertyNode;
1111:            }
1112:
1113:            protected void prepareLogicOperator(AST operator)
1114:                    throws SemanticException {
1115:                ((OperatorNode) operator).initialize();
1116:            }
1117:
1118:            protected void prepareArithmeticOperator(AST operator)
1119:                    throws SemanticException {
1120:                ((OperatorNode) operator).initialize();
1121:            }
1122:
1123:            public static void panic() {
1124:                throw new QueryException("TreeWalker: panic");
1125:            }
1126:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.