You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by je...@apache.org on 2010/11/26 08:44:12 UTC

svn commit: r1039260 - in /incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src: main/java/org/apache/chemistry/opencmis/inmemory/query/ test/java/org/apache/chemistry/opencmis/inmemory/query/

Author: jens
Date: Fri Nov 26 07:44:12 2010
New Revision: 1039260

URL: http://svn.apache.org/viewvc?rev=1039260&view=rev
Log:
cleanup of Query exception handling

Modified:
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/AbstractQueryTest.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryParseTest.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java?rev=1039260&r1=1039259&r2=1039260&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java Fri Nov 26 07:44:12 2010
@@ -22,8 +22,6 @@
  */
 package org.apache.chemistry.opencmis.inmemory.query;
 
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
@@ -44,6 +42,8 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.Cardinality;
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
 import org.apache.chemistry.opencmis.commons.enums.PropertyType;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.DocumentVersion;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.Filing;
@@ -58,7 +58,6 @@ import org.apache.chemistry.opencmis.ser
 import org.apache.chemistry.opencmis.server.support.query.CmisQueryWalker;
 import org.apache.chemistry.opencmis.server.support.query.CmisSelector;
 import org.apache.chemistry.opencmis.server.support.query.ColumnReference;
-import org.apache.chemistry.opencmis.server.support.query.FunctionReference;
 import org.apache.chemistry.opencmis.server.support.query.QueryObject;
 import org.apache.chemistry.opencmis.server.support.query.QueryObject.SortSpec;
 import org.apache.chemistry.opencmis.server.support.query.QueryUtil;
@@ -105,27 +104,10 @@ public class InMemoryQueryProcessor {
         return objList;
     }
 
-    public CmisQueryWalker processQuery(String statement) throws UnsupportedEncodingException, IOException,
-            RecognitionException {
-        CmisQueryWalker walker = QueryUtil.getWalker(statement);
-        walker.query(queryObj, null);
-        String errMsg = walker.getErrorMessageString();
-        if (null != errMsg) {
-            throw new RuntimeException("Walking of statement failed with error: \n   " + errMsg
-                    + "\n   Statement was: " + statement);
-        }
+    public void processQueryAndCatchExc(String statement) {
+        QueryUtil queryUtil = new QueryUtil();
+        CmisQueryWalker walker = queryUtil.traverseStatementAndCatchExc(statement, queryObj, null);
         whereTree = walker.getWherePredicateTree();
-        return walker;
-    }
-
-    public CmisQueryWalker processQueryAndCatchExc(String statement) {
-        try {
-            return processQuery(statement);
-        } catch (RecognitionException e) {
-            throw new RuntimeException("Walking of statement failed with RecognitionException error: \n   " + e);
-        } catch (Exception e) {
-            throw new RuntimeException("Walking of statement failed with other exception: \n   " + e);
-        }
     }
 
     public ObjectList buildResultList(TypeManager tm, String user, Boolean includeAllowableActions,
@@ -200,9 +182,9 @@ public class InMemoryQueryProcessor {
                     else if (propVal2 == null)
                         result = 1;
                     else
-                        result = ((Comparable) propVal1).compareTo(propVal2);
+                        result = ((Comparable<Object>) propVal1).compareTo(propVal2);
                 } else {
-                    String funcName = ((FunctionReference) sel).getName();
+                    // String funcName = ((FunctionReference) sel).getName();
                     // evaluate function here, currently ignore
                     result = 0;
                 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/AbstractQueryTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/AbstractQueryTest.java?rev=1039260&r1=1039259&r2=1039260&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/AbstractQueryTest.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/AbstractQueryTest.java Fri Nov 26 07:44:12 2010
@@ -18,9 +18,6 @@
  */
 package org.apache.chemistry.opencmis.inmemory.query;
 
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
@@ -28,39 +25,33 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.antlr.runtime.ANTLRInputStream;
-import org.antlr.runtime.CharStream;
-import org.antlr.runtime.CommonTokenStream;
 import org.antlr.runtime.RecognitionException;
-import org.antlr.runtime.TokenSource;
-import org.antlr.runtime.TokenStream;
-import org.antlr.runtime.tree.CommonTree;
-import org.antlr.runtime.tree.CommonTreeNodeStream;
 import org.antlr.runtime.tree.Tree;
 import org.apache.chemistry.opencmis.commons.definitions.PropertyBooleanDefinition;
 import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
 import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition;
 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanDefinitionImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl;
 import org.apache.chemistry.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
 import org.apache.chemistry.opencmis.inmemory.types.PropertyCreationHelper;
 import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictLexer;
-import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictParser;
 import org.apache.chemistry.opencmis.server.support.query.CmisQueryWalker;
 import org.apache.chemistry.opencmis.server.support.query.PredicateWalkerBase;
 import org.apache.chemistry.opencmis.server.support.query.QueryObject;
-import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictParser_CmisBaseGrammar.query_return;
+import org.apache.chemistry.opencmis.server.support.query.QueryUtil;
 
 public abstract class AbstractQueryTest {
 
-    protected CommonTree parserTree; // the ANTLR tree after parsing phase
-    protected CommonTree walkerTree; // the ANTLR tree after walking phase
+    protected CmisQueryWalker walker; // the walker object
     protected QueryObject queryObj;
     PredicateWalkerBase predicateWalker;
     protected TypeDefinition myType, myTypeCopy, bookType;
-
+    protected QueryUtil queryUtil;
+    
     protected static final String MY_DOC_TYPE = "MyDocType";
     protected static final String MY_DOC_TYPE_COPY = "MyDocTypeCopy";
     protected static final String BOOL_PROP = "MyBooleanProp";
@@ -76,52 +67,25 @@ public abstract class AbstractQueryTest 
     protected void setUp(QueryObject qo, PredicateWalkerBase pw) throws Exception {
             queryObj = qo;
             predicateWalker = pw;
+            queryUtil = new QueryUtil();
     }
 
     protected void tearDown() throws Exception {
     }
 
-    protected CmisQueryWalker getWalker(String statement) throws UnsupportedEncodingException, IOException, RecognitionException {
-        CharStream input = new ANTLRInputStream(new ByteArrayInputStream(statement.getBytes("UTF-8")));
-        TokenSource lexer = new CmisQlStrictLexer(input);
-        TokenStream tokens = new CommonTokenStream(lexer);
-        CmisQlStrictParser parser = new CmisQlStrictParser(tokens);
-
-        query_return parsedStatement = parser.query();
-//        if (parser.errorMessage != null) {
-//            throw new RuntimeException("Cannot parse query: " + statement + " (" + parser.errorMessage + ")");
-//        }
-        parserTree = (CommonTree) parsedStatement.getTree();            
-        // printTree(tree);
-
-        CommonTreeNodeStream nodes = new CommonTreeNodeStream(parserTree);
-        nodes.setTokenStream(tokens);
-        CmisQueryWalker walker = new CmisQueryWalker(nodes);
-        return walker;
-    }
-
     protected CmisQueryWalker traverseStatement(String statement) throws UnsupportedEncodingException, IOException, RecognitionException {
-        CmisQueryWalker walker = getWalker(statement);
-        walker.query(queryObj, predicateWalker);
-        String errMsg = walker.getErrorMessageString();
-        if (null != errMsg) {
-            fail("Walking of statement failed with error: \n   " + errMsg + 
-                    "\n   Statement was: " + statement);
-        }
-        walkerTree = (CommonTree) walker.getTreeNodeStream().getTreeSource();
-        return walker;
+        walker =  queryUtil.traverseStatement(statement,queryObj, predicateWalker);
+        return walker;        
     }
-
+    
     protected CmisQueryWalker traverseStatementAndCatchExc(String statement) {
-        try {
-            return traverseStatement(statement);
-        } catch (RecognitionException e) {
-            fail("Walking of statement failed with RecognitionException error: \n   " + e); 
-            return null;
-        } catch (Exception e) {
-            fail("Walking of statement failed with other exception: \n   " + e); 
-            return null;
-        }
+        walker = queryUtil.traverseStatementAndCatchExc(statement, queryObj, predicateWalker);
+        return walker;
+    }
+    
+    protected CmisQueryWalker getWalker(String statement) throws UnsupportedEncodingException, IOException, RecognitionException {
+        walker = queryUtil.getWalker(statement);
+        return walker;
     }
     
     protected Tree getWhereTree(Tree root) {

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryParseTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryParseTest.java?rev=1039260&r1=1039259&r2=1039260&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryParseTest.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryParseTest.java Fri Nov 26 07:44:12 2010
@@ -24,13 +24,17 @@ import static org.junit.Assert.assertNul
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.util.List;
 import java.util.Map;
 
+import org.antlr.runtime.FailedPredicateException;
 import org.antlr.runtime.MismatchedTokenException;
 import org.antlr.runtime.RecognitionException;
 import org.antlr.runtime.tree.CommonTree;
 import org.antlr.runtime.tree.Tree;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
 import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictLexer;
 import org.apache.chemistry.opencmis.server.support.query.CmisQueryWalker;
 import org.apache.chemistry.opencmis.server.support.query.CmisSelector;
@@ -60,6 +64,17 @@ public class QueryParseTest extends Abst
     }
 
     @Test
+    public void simpleFailTest() {
+        String statement = "SELECT * TO MyType ORDER BY abc.def ASC";
+//        String statement = "SELECT dsfj disfj dsifj dsoijfß039fi ";
+        try {
+            CmisQueryWalker walker = traverseStatement(statement);
+            fail("Errornous statement should throw exception.");
+        } catch (Exception e) {
+            LOG.debug("Exception in simpleFailTest: " + e);
+        }
+    }
+    
     public void simpleSelectTest1() throws Exception {
         String statement = "SELECT SCORE() FROM cmis:document";
 
@@ -155,7 +170,7 @@ public class QueryParseTest extends Abst
             CmisQueryWalker walker = traverseStatement(statement);
             fail("Walking of statement should with RecognitionException but succeeded");
         } catch (Exception e) {
-            assertTrue(e instanceof RecognitionException || e instanceof MismatchedTokenException);
+            assertTrue(e instanceof CmisInvalidArgumentException);
         }
 
     }
@@ -194,6 +209,17 @@ public class QueryParseTest extends Abst
         assertEquals("abc123", key);
         assertEquals("MyType", types.get(key));
     }
+    
+    @Test
+    public void simpleFromTest4() throws Exception {
+        String statement = "SELECT X.aaa FROM MyType AS X WHERE 10 = ANY X.aaa ";
+        CmisQueryWalker walker = traverseStatementAndCatchExc(statement);
+        Map<String,String> types = queryObj.getTypes();
+        assertTrue(1 == types.size());
+        String key = types.keySet().iterator().next();
+        assertEquals("X", key);
+        assertEquals("MyType", types.get(key));
+    }
 
     @Test
     public void simpleWhereTest() throws Exception {
@@ -289,6 +315,7 @@ public class QueryParseTest extends Abst
         String statement = "SELECT p1, p2, p3.t3 mycol FROM MyType AS MyAlias WHERE p1='abc' and p2=123 ORDER BY abc.def ASC";
         try {
             getWalker(statement);
+            Tree parserTree = (Tree) walker.getTreeNodeStream().getTreeSource();
             printTree(parserTree, statement);
 
         } catch (Exception e) {
@@ -303,6 +330,7 @@ public class QueryParseTest extends Abst
 
         try {
             getWalker(statement);
+            Tree parserTree = (Tree) walker.getTreeNodeStream().getTreeSource();
             Tree whereTree = getWhereTree(parserTree);
             printTree(whereTree);
             LOG.info("Evaluate WHERE subtree: ...");
@@ -466,14 +494,25 @@ public class QueryParseTest extends Abst
         String statement = "SELECT * FROM T1 MyAlias JOIN T2 AS MyAlias";
         try {
             traverseStatement(statement);
+            fail("Parsing statement " + statement + " should fail.");
+        } catch (RecognitionException e) {
+            assertTrue(e instanceof FailedPredicateException);
+            LOG.debug("duplicatedAliasTestFrom(), exception: " + e);
+            // walker.reportError(e);
+            String errorMessage = queryUtil.getErrorMessage(e);
+            LOG.debug("");
+            LOG.debug("duplicatedAliasTestFrom(), error message: " + errorMessage);
+            assertTrue(e.toString().contains("more than once as alias in a from"));
+            assertTrue(errorMessage.contains("more than once as alias in a from"));
         } catch (Exception e) {
-            assertTrue(e.getMessage().contains("more than once as alias in a from"));
+            fail("Parsing statement " + statement + " should fail with RecognitionException, but was: " + e.getClass());
         }
     }
 
     private void checkTreeWhere(String statement) {
         LOG.info("\ncheckTreeWhere: " + statement);
         traverseStatementAndCatchExc(statement);
+        Tree walkerTree = (Tree) walker.getTreeNodeStream().getTreeSource();
         Tree whereTree = getWhereTree(walkerTree);
         evalWhereTree(whereTree);
     }
@@ -817,4 +856,5 @@ public class QueryParseTest extends Abst
     private void evalTimeLiteral(Tree node) {
         assertEquals(0, node.getChildCount());
     }
+
 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java?rev=1039260&r1=1039259&r2=1039260&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java Fri Nov 26 07:44:12 2010
@@ -25,20 +25,24 @@ import static org.junit.Assert.fail;
 import java.util.List;
 import java.util.Map;
 
+import org.antlr.runtime.RecognitionException;
 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
-import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
 import org.apache.chemistry.opencmis.inmemory.TypeManagerImpl;
+import org.apache.chemistry.opencmis.server.support.query.CmisQueryException;
 import org.apache.chemistry.opencmis.server.support.query.CmisQueryWalker;
 import org.apache.chemistry.opencmis.server.support.query.CmisSelector;
 import org.apache.chemistry.opencmis.server.support.query.ColumnReference;
 import org.apache.chemistry.opencmis.server.support.query.QueryObject;
 import org.apache.chemistry.opencmis.server.support.query.QueryObject.SortSpec;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 public class QueryTypesTest extends AbstractQueryTest {
     
+    private static Log LOG = LogFactory.getLog(QueryTypesTest.class);
     private TypeManagerImpl tm;
 
     @Before
@@ -96,8 +100,9 @@ public class QueryTypesTest extends Abst
             verifyResolveSelect(statement);
             fail("Select of unknown property in type should fail.");
         } catch (Exception e) {
-            assertTrue(e instanceof CmisInvalidArgumentException);
-            assertTrue(e.getMessage().contains("is not a valid property query name in"));
+            assertTrue(e instanceof RecognitionException);
+            LOG.debug("resolveTypesTest6(), e: " + e.getMessage());
+            assertTrue(e.toString().contains("is not a valid property query name in"));
         }
     }
 
@@ -108,8 +113,8 @@ public class QueryTypesTest extends Abst
             verifyResolveSelect(statement);
             fail("Select of unknown property in type should fail.");
         } catch (Exception e) {
-            assertTrue(e instanceof CmisInvalidArgumentException);
-            assertTrue(e.getMessage().contains("is not a property query name in any"));
+            assertTrue(e instanceof RecognitionException);
+            assertTrue(e.toString().contains("is not a property query name in any"));
         }
     }
 
@@ -191,8 +196,8 @@ public class QueryTypesTest extends Abst
             traverseStatement(statement);
             fail("Select with an unqualified property that is not unique should fail.");
         } catch (Exception e) {
-            assertTrue(e instanceof CmisInvalidArgumentException);
-            assertTrue(e.getMessage().contains("is not a unique property query name within the types in from"));
+            assertTrue(e instanceof RecognitionException);
+            assertTrue(e.toString().contains("is not a unique property query name within the types in from"));
         }
     }
 
@@ -303,6 +308,20 @@ public class QueryTypesTest extends Abst
         }
     }
 
+    @Test
+    public void resolveTypesWhereWithTwoFromsQualifiedWithAlias2() throws Exception {
+//        String statement = "SELECT X.aaa FROM MyType AS X WHERE 10 = ANY X.aaa ";
+        String statement = "SELECT MyBookAlias.Title FROM BookType AS MyBookAlias WHERE MyBookAlias.ISBN = '100'"; 
+        CmisQueryWalker walker = traverseStatement(statement);
+        List<CmisSelector> wheres = queryObj.getWhereReferences();
+        assertTrue(1 == wheres.size());
+        for (CmisSelector where : wheres) {
+            assertTrue(where instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) where);
+            assertEquals(colRef.getTypeDefinition(), bookType);
+        }
+    }
+    
     private void verifyResolveWhere(String statement) throws Exception {
         CmisQueryWalker walker = traverseStatement(statement);
         Map<String,String> types = queryObj.getTypes();
@@ -325,8 +344,8 @@ public class QueryTypesTest extends Abst
             CmisQueryWalker walker = traverseStatement(statement);
             fail("Select with an unqualified property that is not unique should fail.");
         } catch (Exception e) {
-            assertTrue(e instanceof CmisInvalidArgumentException);
-            assertTrue(e.getMessage().contains("is not a unique property query name within the types in from"));
+            assertTrue(e instanceof RecognitionException);
+            assertTrue(e.toString().contains("is not a unique property query name within the types in from"));
         }
     }
     
@@ -403,5 +422,26 @@ public class QueryTypesTest extends Abst
                 fail("Unexpected type in JOIN reference");
         }
     }
-
+    
+    @Test
+    public void resolveJoinTypesWithAlias() throws Exception {
+        String statement = "SELECT Y.ISBN, X.MyBooleanProp, Y.Author FROM (MyDocType AS X JOIN BookType AS Y ON X.MyStringProp = Y.Title) "+
+                           "WHERE ('Joe' = ANY Y.Author)";
+//        "SELECT    Y.CLAIM_NUM, X.PROPERTY_ADDRESS, Y.DAMAGE_ESTIMATES " +
+//        "FROM   ( POLICY AS X JOIN CLAIMS AS Y ON X.POLICY_NUM = Y.POLICY_NUM ) " +
+//        "WHERE ( 100000 = ANY Y.DAMAGE_ESTIMATES )";
+        CmisQueryWalker walker = traverseStatement(statement);
+        List<CmisSelector> joins = queryObj.getJoinReferences();
+        assertTrue(2 == joins.size());
+        for (CmisSelector join : joins) {
+            assertTrue(join instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) join);
+            if (myType.equals(colRef.getTypeDefinition())) {
+                assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP));
+            } else if (bookType.equals(colRef.getTypeDefinition())) {
+                assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP));
+            } else 
+                fail("Unexpected type in JOIN reference");
+        }
+    }
 }