You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fg...@apache.org on 2011/04/26 15:34:32 UTC

svn commit: r1096750 - in /chemistry/opencmis/trunk/chemistry-opencmis-server: chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/ chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmi...

Author: fguillaume
Date: Tue Apr 26 13:34:32 2011
New Revision: 1096750

URL: http://svn.apache.org/viewvc?rev=1096750&view=rev
Log:
Make parser and AbstractPredicateWalker check type qualifiers for IN_TREE, IN_FOLDER, CONTAINS; more type verification in QueryObject

Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractPredicateWalker.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/PredicateWalker.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java?rev=1096750&r1=1096749&r2=1096750&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java Tue Apr 26 13:34:32 2011
@@ -603,7 +603,7 @@ public class EvalQueryTest extends Abstr
             res = doQuery(statement);
             fail("Unknown type in folder should throw exception");
         } catch (Exception e) {
-            assertTrue(e.toString().contains("must be in FROM list"));
+            assertTrue(e.toString().contains("is neither a type query name nor an alias"));
             log.debug("expected Exception: " + e);
         }
     }
@@ -632,7 +632,7 @@ public class EvalQueryTest extends Abstr
             res = doQuery(statement);
             fail("Unknown type in folder should throw exception");
         } catch (Exception e) {
-            assertTrue(e.toString().contains("must be in FROM list"));
+            assertTrue(e.toString().contains("is neither a type query name nor an alias"));
             log.debug("expected Exception: " + e);
         }
     }

Modified: 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/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java?rev=1096750&r1=1096749&r2=1096750&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java Tue Apr 26 13:34:32 2011
@@ -20,12 +20,15 @@ package org.apache.chemistry.opencmis.in
 
 import static org.junit.Assert.*;
 
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
 import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.tree.Tree;
 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
 import org.apache.chemistry.opencmis.inmemory.TypeManagerImpl;
+import org.apache.chemistry.opencmis.server.support.query.AbstractPredicateWalker;
 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;
@@ -41,6 +44,16 @@ public class QueryTypesTest extends Abst
 
     private static final Log LOG = LogFactory.getLog(QueryTypesTest.class);
     private TypeManagerImpl tm;
+    private TestPredicateWalker pw;
+
+    public static class TestPredicateWalker extends AbstractPredicateWalker {
+        List<Integer> ids = new LinkedList<Integer>();
+        @Override
+        public Object walkId(Tree node) {
+            ids.add(node.getTokenStartIndex());
+            return null;
+        }
+    }
 
     @Before
     public void setUp() {
@@ -54,7 +67,9 @@ public class QueryTypesTest extends Abst
         }
 
         // initialize query object with type manager
-        super.setUp(new QueryObject(tm), null);
+        // and test the abstract predicate walker
+        pw = new TestPredicateWalker();
+        super.setUp(new QueryObject(tm), pw);
     }
 
     @After
@@ -170,6 +185,37 @@ public class QueryTypesTest extends Abst
     }
 
     @Test
+    public void resolveTypesWithTwoFromsSameTypeCorrectlyQualified()
+            throws Exception {
+        String statement = "SELECT A.Title FROM BookType A JOIN BookType B";
+
+        CmisQueryWalker walker = traverseStatement(statement);
+        assertNotNull(walker);
+        Map<String, String> types = queryObj.getTypes();
+        assertEquals(2, types.size());
+        List<CmisSelector> selects = queryObj.getSelectReferences();
+        assertEquals(1, selects.size());
+        ColumnReference colRef = ((ColumnReference) selects.get(0));
+        assertEquals(bookType, colRef.getTypeDefinition());
+        assertEquals(TITLE_PROP, colRef.getPropertyQueryName());
+        assertEquals("A", colRef.getQualifier());
+    }
+
+    @Test
+    public void resolveTypesWithTwoFromsSameTypeAmbiguouslyQualified()
+            throws Exception {
+        String statement = "SELECT BookType.Title FROM BookType A JOIN BookType B";
+        try {
+            traverseStatement(statement);
+            fail("Select with an ambiguously qualified property should fail.");
+        } catch (Exception e) {
+            assertTrue(e instanceof RecognitionException);
+            assertTrue(e.toString().contains(
+                    "BookType is an ambiguous type query name"));
+        }
+    }
+
+    @Test
     public void resolveTypesWithTwoFromsUnqualified() throws Exception {
         String statement = "SELECT Title, MyStringProp FROM BookType JOIN MyDocType AS MyDocAlias WHERE BookType.ISBN = '100'";
 
@@ -461,4 +507,75 @@ public class QueryTypesTest extends Abst
             }
         }
     }
+
+    @Test
+    public void resolveTypeQualifiers1() throws Exception {
+        String statement = "SELECT Title FROM BookType WHERE IN_TREE(BookType, 'foo')";
+        CmisQueryWalker walker = traverseStatement(statement);
+        assertNotNull(walker);
+        assertEquals("BookType", queryObj.getTypeReference(pw.ids.get(0)));
+    }
+
+    @Test
+    public void resolveTypeQualifiers2() throws Exception {
+        String statement = "SELECT Title FROM BookType B WHERE IN_TREE(B, 'foo')";
+        CmisQueryWalker walker = traverseStatement(statement);
+        assertNotNull(walker);
+        assertEquals("B", queryObj.getTypeReference(pw.ids.get(0)));
+    }
+
+    @Test
+    public void resolveTypeQualifiers3() throws Exception {
+        String statement = "SELECT Title FROM BookType B WHERE IN_TREE(BookType, 'foo')";
+        CmisQueryWalker walker = traverseStatement(statement);
+        assertNotNull(walker);
+        assertEquals("B", queryObj.getTypeReference(pw.ids.get(0)));
+    }
+
+    @Test
+    public void resolveTypeQualifiers4() throws Exception {
+        String statement = "SELECT Title FROM BookType B WHERE IN_TREE(dummy, 'foo')";
+        try {
+            traverseStatement(statement);
+            fail("invalid correlation name should fail");
+        } catch (Exception e) {
+            assertTrue(e instanceof RecognitionException);
+            assertTrue(e.toString().contains(
+                    "dummy is neither a type query name nor an alias"));
+        }
+    }
+
+    @Test
+    public void resolveTypeQualifiers5() throws Exception {
+        String statement = "SELECT B1.Title FROM BookType B1 JOIN BookType B2"
+                + " WHERE IN_TREE(B1, 'foo') OR IN_TREE(B2, 'bar')";
+        CmisQueryWalker walker = traverseStatement(statement);
+        assertNotNull(walker);
+        assertEquals("B1", queryObj.getTypeReference(pw.ids.get(0)));
+        assertEquals("B2", queryObj.getTypeReference(pw.ids.get(1)));
+    }
+
+    @Test
+    public void resolveTypeQualifiers6() throws Exception {
+        String statement = "SELECT B.Title FROM BookType B JOIN MyDocType D"
+                + " WHERE IN_TREE(MyDocType, 'foo')";
+        CmisQueryWalker walker = traverseStatement(statement);
+        assertNotNull(walker);
+        assertEquals("D", queryObj.getTypeReference(pw.ids.get(0)));
+    }
+
+    @Test
+    public void resolveTypeQualifiers7() throws Exception {
+        String statement = "SELECT B1.Title FROM BookType B1 JOIN BookType B2"
+                + " WHERE IN_TREE(BookType, 'foo')";
+        try {
+            traverseStatement(statement);
+            fail("ambiguous correlation name should fail");
+        } catch (Exception e) {
+            assertTrue(e instanceof RecognitionException);
+            assertTrue(e.toString().contains(
+                    "BookType is an ambiguous type query name"));
+        }
+    }
+
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g?rev=1096750&r1=1096749&r2=1096750&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g Tue Apr 26 13:34:32 2011
@@ -257,8 +257,17 @@ search_condition
             queryObj.addWhereReference($mvcr.start, $mvcr.result);
       }
     | ^(CONTAINS qualifier? text_search_expression)
+      {
+            queryObj.addWhereTypeReference($qualifier.start, $qualifier.value);
+      }
     | ^(IN_FOLDER qualifier? search_condition)
+      {
+            queryObj.addWhereTypeReference($qualifier.start, $qualifier.value);
+      }
     | ^(IN_TREE qualifier? search_condition)
+      {
+            queryObj.addWhereTypeReference($qualifier.start, $qualifier.value);
+      }
     | ^(IN column_reference in_value_list)
       {
             queryObj.addWhereReference($column_reference.start, $column_reference.result);

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractPredicateWalker.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractPredicateWalker.java?rev=1096750&r1=1096749&r2=1096750&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractPredicateWalker.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractPredicateWalker.java Tue Apr 26 13:34:32 2011
@@ -131,6 +131,8 @@ public abstract class AbstractPredicateW
             return walkList(node);
         case CmisQlStrictLexer.COL:
             return walkCol(node);
+        case CmisQlStrictLexer.ID:
+            return walkId(node);
         default:
             return walkOtherExpr(node);
         }
@@ -293,4 +295,8 @@ public abstract class AbstractPredicateW
         return null;
     }
 
+    public Object walkId(Tree node) {
+        return null;
+    }
+
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/PredicateWalker.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/PredicateWalker.java?rev=1096750&r1=1096749&r2=1096750&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/PredicateWalker.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/PredicateWalker.java Tue Apr 26 13:34:32 2011
@@ -89,4 +89,6 @@ public interface PredicateWalker extends
 
     Object walkCol(Tree node);
 
+    Object walkId(Tree node);
+
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java?rev=1096750&r1=1096749&r2=1096750&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java Tue Apr 26 13:34:32 2011
@@ -25,6 +25,7 @@ import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.antlr.runtime.tree.Tree;
 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
@@ -66,6 +67,7 @@ public class QueryObject {
 
     // where part
     protected final Map<Integer, CmisSelector> columnReferences = new HashMap<Integer, CmisSelector>();
+    protected final Map<Integer, String> typeReferences = new HashMap<Integer, String>();
 
     // order by part
     protected final List<SortSpec> sortSpecs = new ArrayList<SortSpec>();
@@ -135,6 +137,10 @@ public class QueryObject {
         return columnReferences.get(token);
     }
 
+    public String getTypeReference(Integer token) {
+        return typeReferences.get(token);
+    }
+
     public String getErrorMessage() {
         return errorMessage;
     }
@@ -199,8 +205,8 @@ public class QueryObject {
         return Collections.unmodifiableMap(froms);
     }
 
-    public String getTypeQueryName(String alias) {
-        return froms.get(alias);
+    public String getTypeQueryName(String qualifier) {
+        return froms.get(qualifier);
     }
 
     public TypeDefinition getTypeDefinitionFromQueryName(String queryName) {
@@ -305,7 +311,6 @@ public class QueryObject {
 
     public void addWhereReference(Tree node, CmisSelector reference) {
         LOG.debug("add node to where: " + System.identityHashCode(node));
-
         columnReferences.put(node.getTokenStartIndex(), reference);
         whereReferences.add(reference);
     }
@@ -314,6 +319,12 @@ public class QueryObject {
         return Collections.unmodifiableList(whereReferences);
     }
 
+    public void addWhereTypeReference(Tree node, String qualifier) {
+        if (node != null) {
+            typeReferences.put(node.getTokenStartIndex(), qualifier);
+        }
+    }
+
     // ///////////////////////////////////////////////////////
     // ORDER_BY part
 
@@ -396,6 +407,33 @@ public class QueryObject {
                 }
             }
 
+            // Replace types used as qualifiers (IN_TREE, IN_FOLDER,
+            // CONTAINS) by their corresponding alias (correlation name)
+            for (Entry<Integer, String> en: typeReferences.entrySet()) {
+                Integer obj = en.getKey();
+                String qualifier = en.getValue();
+                String typeQueryName = getReferencedTypeQueryName(qualifier);
+                if (typeQueryName == null) {
+                    throw new CmisQueryException(qualifier
+                            + " is neither a type query name nor an alias.");
+                }
+                if (typeQueryName.equals(qualifier)) {
+                    // try to find an alias for it
+                    String alias = null;
+                    for (Entry<String, String> e : froms.entrySet()) {
+                        String q = e.getKey();
+                        String tqn = e.getValue();
+                        if (!tqn.equals(q) && typeQueryName.equals(tqn)) {
+                            alias = q;
+                            break;
+                        }
+                    }
+                    if (alias != null) {
+                        typeReferences.put(obj, alias);
+                    }
+                }
+            }
+
             return true;
         } catch (CmisQueryException cqe) {
             errorMessage = cqe.getMessage(); // preserve message
@@ -488,17 +526,22 @@ public class QueryObject {
 
     // return type query name for a referenced column (which can be the name
     // itself or an alias
-    protected String getReferencedTypeQueryName(String typeQueryNameOrAlias) {
-        String typeQueryName = froms.get(typeQueryNameOrAlias);
+    protected String getReferencedTypeQueryName(String qualifier) {
+        String typeQueryName = froms.get(qualifier);
         if (null == typeQueryName) {
             // if an alias was defined but still the original is used we have to
             // search case: SELECT T.p FROM T AS TAlias
+            String q = null;
             for (String tqn : froms.values()) {
-                if (typeQueryNameOrAlias.equals(tqn)) {
-                    return tqn;
+                if (qualifier.equals(tqn)) {
+                    if (q != null) {
+                        throw new CmisQueryException(qualifier
+                                + " is an ambiguous type query name.");
+                    }
+                    q = tqn;
                 }
             }
-            return null;
+            return q;
         } else {
             return typeQueryName;
         }