Author: stliu
Date: 2009-12-29 15:08:04 -0500 (Tue, 29 Dec 2009)
New Revision: 18348
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/NodeTraverser.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/criteria/LongInElementsTest.java
Log:
HHH-2166 - Long 'in' lists in queries results in a Java stack overflow exception.
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java 2009-12-29
19:58:52 UTC (rev 18347)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java 2009-12-29
20:08:04 UTC (rev 18348)
@@ -580,7 +580,7 @@
if ( dotRoot != null ) {
// we are already processing a dot-structure
if ( ASTUtil.isSubtreeChild( dotRoot, node ) ) {
- // igndore it...
+ // ignore it...
return;
}
else {
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/NodeTraverser.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/NodeTraverser.java 2009-12-29
19:58:52 UTC (rev 18347)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/NodeTraverser.java 2009-12-29
20:08:04 UTC (rev 18348)
@@ -25,14 +25,14 @@
package org.hibernate.hql.ast.util;
import antlr.collections.AST;
-import java.util.Map;
-import java.util.HashMap;
+import java.util.Stack;
/**
* A visitor for traversing an AST tree.
*
* @author Steve Ebersole
* @author Philip R. "Pib" Burns.
+ * @author Strong Liu
*
*/
@@ -46,7 +46,7 @@
public NodeTraverser( VisitationStrategy strategy ) {
this.strategy = strategy;
}
-
+
/**
* Traverse the AST tree depth first.
*
@@ -57,98 +57,24 @@
* Note that the AST passed in is not visited itself. Visitation
* starts with its children.
* </p>
- * <p>
- * The current code for traverseDepthFirst uses iteration to walk
- * the tree. This corrects stack overflow problems for constructs
- * such as "x in (:x)" where ":x" specifies a large
number of
- * items.
- * </p>
*/
-
public void traverseDepthFirst( AST ast ) {
- // Root AST node cannot be null or
- // traversal of its subtree is impossible.
if ( ast == null ) {
- throw new IllegalArgumentException( "node to traverse cannot be null!" );
+ throw new IllegalArgumentException(
+ "node to traverse cannot be null!" );
}
- // Map to hold parents of each
- // AST node. Unfortunately the AST
- // interface does not provide a method
- // for finding the parent of a node, so
- // we use the Map to save them.
-
- Map parentNodes = new HashMap();
-
- // Start tree traversal with first child
- // of the specified root AST node.
-
- AST currentNode = ast.getFirstChild();
-
- // Remember parent of first child.
-
- parentNodes.put(currentNode, ast);
-
- // Iterate through nodes, simulating
- // recursive tree traversal, and add them
- // to queue in proper order for later
- // linear traversal. This "flattens" the
- // into a linear list of nodes which can
- // be visited non-recursively.
-
- while ( currentNode != null ) {
- // Visit the current node.
-
- strategy.visit( currentNode );
-
- // Move down to current node's first child
- // if it exists.
-
- AST childNode = currentNode.getFirstChild();
-
- // If the child is not null, make it
- // the current node.
-
- if ( childNode != null ) {
- // Remember parent of the child.
-
- parentNodes.put( childNode, currentNode );
-
- // Make child the current node.
-
- currentNode = childNode;
-
- continue;
- }
-
- while ( currentNode != null ) {
- // Move to next sibling if any.
-
- AST siblingNode = currentNode.getNextSibling();
-
- if (siblingNode != null) {
- // Get current node's parent.
- // This is also the parent of the
- // sibling node.
-
- AST parentNode = (AST) parentNodes.get(currentNode);
-
- // Remember parent of sibling.
-
- parentNodes.put(siblingNode, parentNode);
-
- // Make sibling the current node.
-
- currentNode = siblingNode;
-
- break;
+ AST node = ast.getFirstChild();
+ Stack stack = new Stack();
+ if ( node != null ) {
+ stack.push( node );
+ while (!stack.empty()) {
+ node = (AST) stack.pop();
+ strategy.visit( node );
+ if ( node.getFirstChild() != null ) {
+ stack.push( node.getFirstChild() );
}
- // Move up to parent if no sibling.
- // If parent is root node, we're done.
-
- currentNode = (AST) parentNodes.get(currentNode);
-
- if (currentNode.equals(ast)) {
- currentNode = null;
+ if ( node.getNextSibling() != null ) {
+ stack.push( node.getNextSibling() );
}
}
}
Modified:
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/criteria/LongInElementsTest.java
===================================================================
---
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/criteria/LongInElementsTest.java 2009-12-29
19:58:52 UTC (rev 18347)
+++
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/criteria/LongInElementsTest.java 2009-12-29
20:08:04 UTC (rev 18348)
@@ -41,6 +41,7 @@
/**
*
* HHH-2166 Long "in" lists in queries results in a Java stack overflow
exception.
+ * to reproduce this issue, you should add
"<argLine>-Xss128k</argLine>" to the surefire plugin (test on Fedora
12)
*
* @author Strong Liu
*/
Show replies by date