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/06/18 09:02:55 UTC

svn commit: r955857 - in /incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src: main/antlr3/org/apache/chemistry/opencmis/inmemory/query/ main/java/org/apache/chemistry/opencmis/inmemory/query/ test/java/o...

Author: jens
Date: Fri Jun 18 07:02:55 2010
New Revision: 955857

URL: http://svn.apache.org/viewvc?rev=955857&view=rev
Log:
CMIS-216
add support for operators IN, NOT IN, IN ANY, NOT IN ANY, =ANY for query in in-memory server

Modified:
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/antlr3/org/apache/chemistry/opencmis/inmemory/query/CmisQueryWalker.g
    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/EvalQueryTest.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/antlr3/org/apache/chemistry/opencmis/inmemory/query/CmisQueryWalker.g
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/antlr3/org/apache/chemistry/opencmis/inmemory/query/CmisQueryWalker.g?rev=955857&r1=955856&r2=955857&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/antlr3/org/apache/chemistry/opencmis/inmemory/query/CmisQueryWalker.g (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/antlr3/org/apache/chemistry/opencmis/inmemory/query/CmisQueryWalker.g Fri Jun 18 07:02:55 2010
@@ -191,9 +191,6 @@ table_reference:
 
 table_join:
     ^(JOIN join_kind one_table join_specification?)
-    {
-      //throw new UnsupportedOperationException("JOIN");
-    }
     ;
 
 one_table:
@@ -236,7 +233,10 @@ search_condition
     | ^(NOT_LIKE search_condition search_condition)
     | ^(IS_NULL search_condition) 
     | ^(IS_NOT_NULL search_condition) 
-    | ^(EQ_ANY search_condition search_condition)
+    | ^(EQ_ANY literal column_reference)
+      {
+      	  queryObj.addSelectReference($column_reference.start, $column_reference.result);
+      }
     | ^(IN_ANY search_condition in_value_list )
     | ^(NOT_IN_ANY search_condition in_value_list)
     | ^(CONTAINS qualifier? text_search_expression)
@@ -244,9 +244,12 @@ search_condition
     | ^(IN_TREE qualifier? search_condition)
     | ^(IN column_reference in_value_list)
       {
-           LOG.debug("IN list: " + $in_value_list.inList);
+      	  queryObj.addSelectReference($column_reference.start, $column_reference.result);
       }
     | ^(NOT_IN column_reference in_value_list)
+      {
+      	  queryObj.addSelectReference($column_reference.start, $column_reference.result);
+      }
     | value_expression
       {
           LOG.debug("  add node to where: " + $value_expression.start + " id: " + System.identityHashCode($value_expression.start));

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=955857&r1=955856&r2=955857&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 Jun 18 07:02:55 2010
@@ -464,24 +464,107 @@ public class InMemoryQueryProcessor impl
         return matches1 || matches2;
     }
 
-    private boolean evalWhereIn(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
-        throw new RuntimeException("Operator IN not supported in InMemory server.");
+    private boolean evalWhereIn(StoredObject so, Tree node, Tree colNode, Tree listNode) {
+        ColumnReference colRef = getColumnReference(colNode);
+        TypeDefinition td = colRef.getTypeDefinition();
+        PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+        PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+        List<Object> literals = onLiteralList(listNode);
+        if (pd.getCardinality() != Cardinality.SINGLE)
+            throw new RuntimeException("Operator IN only is allowed on single-value properties ");
+        else if (lVal == null)
+            return false;
+        else {
+            Object prop= lVal.getFirstValue();
+            if (literals.contains(prop))
+                return true;
+            else
+                return false;
+        }
     }
 
     private boolean evalWhereNotIn(StoredObject so, Tree node, Tree colNode, Tree listNode) {
-        throw new RuntimeException("Operator NOT IN not supported in InMemory server.");
+        // Note just return !evalWhereIn(so, node, colNode, listNode) is wrong, because
+        // then it evaluates to true for null values (not set properties).
+        ColumnReference colRef = getColumnReference(colNode);
+        TypeDefinition td = colRef.getTypeDefinition();
+        PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+        PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+        List<Object> literals = onLiteralList(listNode);
+        if (pd.getCardinality() != Cardinality.SINGLE)
+            throw new RuntimeException("Operator IN only is allowed on single-value properties ");
+        else if (lVal == null)
+            return false;
+        else {
+            Object prop= lVal.getFirstValue();
+            if (literals.contains(prop))
+                return false;
+            else
+                return true;
+        }
     }
 
     private boolean evalWhereInAny(StoredObject so, Tree node, Tree colNode, Tree listNode) {
-        throw new RuntimeException("Operator IN ANY not supported in InMemory server.");
+        ColumnReference colRef = getColumnReference(colNode);
+        TypeDefinition td = colRef.getTypeDefinition();
+        PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+        PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+        List<Object> literals = onLiteralList(listNode);
+        if (pd.getCardinality() != Cardinality.MULTI)
+            throw new RuntimeException("Operator ANY...IN only is allowed on multi-value properties ");
+        else if (lVal == null)
+            return false;
+        else {
+            List<?> props= lVal.getValues();
+            for (Object prop : props) {
+                LOG.debug("comparing with: " + prop);
+                if (literals.contains(prop))
+                    return true;
+            }
+            return false;
+        }
     }
 
     private boolean evalWhereNotInAny(StoredObject so, Tree node, Tree colNode, Tree listNode) {
-        throw new RuntimeException("Operator NOT IN ANY not supported in InMemory server.");
+        // Note just return !evalWhereInAny(so, node, colNode, listNode) is wrong, because
+        // then it evaluates to true for null values (not set properties).
+        ColumnReference colRef = getColumnReference(colNode);
+        TypeDefinition td = colRef.getTypeDefinition();
+        PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+        PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+        List<Object> literals = onLiteralList(listNode);
+        if (pd.getCardinality() != Cardinality.MULTI)
+            throw new RuntimeException("Operator ANY...IN only is allowed on multi-value properties ");
+        else if (lVal == null)
+            return false;
+        else {
+            List<?> props= lVal.getValues();
+            for (Object prop : props) {
+                LOG.debug("comparing with: " + prop);
+                if (literals.contains(prop))
+                    return false;
+            }
+            return true;
+        }    
     }
 
-    private boolean evalWhereEqAny(StoredObject so, Tree node, Tree colNode, Tree listNode) {
-        throw new RuntimeException("Operator = ANY not supported in InMemory server.");
+    private boolean evalWhereEqAny(StoredObject so, Tree node, Tree literalNode, Tree colNode) {
+        ColumnReference colRef = getColumnReference(colNode);
+        TypeDefinition td = colRef.getTypeDefinition();
+        PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+        PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+        Object literal = onLiteral(literalNode);
+        if (pd.getCardinality() != Cardinality.MULTI)
+            throw new RuntimeException("Operator = ANY only is allowed on multi-value properties ");
+        else if (lVal == null)
+            return false;
+        else {
+            List<?> props= lVal.getValues();
+            if (props.contains(literal))
+                return true;
+            else
+                return false;
+        }
     }
 
     private boolean evalWhereIsNull(StoredObject so, Tree node, Tree child) {
@@ -599,6 +682,15 @@ public class InMemoryQueryProcessor impl
             return null;
         }
     }
+ 
+    private List<Object> onLiteralList(Tree node) {
+        List<Object> res = new ArrayList<Object>(node.getChildCount());
+        for (int i=0; i<node.getChildCount(); i++) {
+            Tree literal =  node.getChild(i);
+            res.add(onLiteral(literal));
+        }
+        return res;
+    }
     
     private Integer compareTo(StoredObject so, Tree leftChild, Tree rightChild) {
         Object rVal = onLiteral(rightChild);

Modified: incubator/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/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java?rev=955857&r1=955856&r2=955857&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java Fri Jun 18 07:02:55 2010
@@ -633,7 +633,103 @@ public class EvalQueryTest extends Abstr
             log.debug("expected Exception: " + e);
         }
     }
+    
+    @Test
+    public void testIn() {
+        String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " IN ('Alpha', 'Beta', 'Gamma')";
+        ObjectList res = doQuery(statement);
+        assertEquals(3, res.getObjects().size());
+        assertTrue(resultContains("alpha", res));    
+        assertTrue(resultContains("beta", res));    
+        assertTrue(resultContains("gamma", res));    
 
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " IN ('Theta', 'Pi', 'Rho')";
+        res = doQuery(statement);
+        assertEquals(0, res.getObjects().size());
+    }
+    
+    @Test
+    public void testNotIn() {
+        String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " NOT IN ('Alpha', 'Beta', 'Gamma')";
+        ObjectList res = doQuery(statement);
+        assertEquals(2, res.getObjects().size());
+        assertTrue(resultContains("delta", res));    
+        assertTrue(resultContains("epsilon", res));    
+
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " NOT IN ('Theta', 'Pi', 'Rho')";
+        res = doQuery(statement);
+        assertEquals(5, res.getObjects().size());
+        assertTrue(resultContains("alpha", res));    
+        assertTrue(resultContains("beta", res));    
+        assertTrue(resultContains("gamma", res));    
+        assertTrue(resultContains("delta", res));    
+        assertTrue(resultContains("epsilon", res));    
+    }
+    
+    @Test
+    public void testMultiValueInAny() {
+        dataCreator.createMultiValueDocuments();
+
+        String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE + " IN ('red', 'black', 'grey')";
+        ObjectList res = doQuery(statement);
+        assertEquals(2, res.getObjects().size());
+        assertTrue(resultContains("mv-alpha", res));    
+        assertTrue(resultContains("mv-beta", res));    
+
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE + " IN ('green', 'black', 'grey')";
+        res = doQuery(statement);
+        assertEquals(1, res.getObjects().size());
+        assertTrue(resultContains("mv-alpha", res));    
+
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE + " IN ('white', 'black', 'grey')";
+        res = doQuery(statement);
+        assertEquals(0, res.getObjects().size());
+    }
+    
+    @Test
+    public void testMultiValueNotInAny() {
+        dataCreator.createMultiValueDocuments();
+
+        String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE + " NOT IN ('red', 'black', 'grey')";
+        ObjectList res = doQuery(statement);
+        assertEquals(0, res.getObjects().size());
+
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE + " NOT IN ('green', 'black', 'grey')";
+        res = doQuery(statement);
+        assertEquals(1, res.getObjects().size());
+        assertTrue(resultContains("mv-beta", res));    
+
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE + " NOT IN ('white', 'black', 'grey')";
+        res = doQuery(statement);
+        assertEquals(2, res.getObjects().size());
+        assertTrue(resultContains("mv-alpha", res));    
+        assertTrue(resultContains("mv-beta", res));    
+    }
+
+    @Test
+    public void testMultiValueEqAny() {
+        dataCreator.createMultiValueDocuments();
+
+        String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE 'red' = ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE ;
+        ObjectList res = doQuery(statement);
+        assertEquals(2, res.getObjects().size());
+        assertTrue(resultContains("mv-alpha", res));    
+        assertTrue(resultContains("mv-beta", res));
+
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE 'black' = ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING_MULTI_VALUE ;
+        res = doQuery(statement);
+        assertEquals(0, res.getObjects().size());
+        
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE 'black' = ANY " + UnitTestTypeSystemCreator.PROP_ID_STRING;
+        try {
+            res = doQuery(statement);
+            fail("Unknown = ANY with single value prop should throw exception");
+        } catch (Exception e) {
+            assertTrue(e.toString().contains("only is allowed on multi-value properties"));
+            log.debug("expected Exception: " + e);
+        }
+    }
+    
     private ObjectList doQuery(String queryString) {
         log.debug("\nExecuting query: " + queryString);
         ObjectList res = fDiscSvc.query(fRepositoryId, queryString, false, false,

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.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/QueryTestDataCreator.java?rev=955857&r1=955856&r2=955857&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java Fri Jun 18 07:02:55 2010
@@ -169,7 +169,42 @@ public class QueryTestDataCreator {
             }};           
         doc5 = createDocument("epsilon", rootFolderId, COMPLEX_TYPE, propertyMap5);
 
-}
+    }
+    
+    @SuppressWarnings("serial")
+    public void createMultiValueDocuments() {
+        final List<String> mvProps1 = 
+            new ArrayList<String>() {
+            { 
+                add("red");
+                add("green");
+                add("blue");
+            }};
+        
+        final Map<String, Object> propertyMap1 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_STRING_MULTI_VALUE, mvProps1);
+                put(PROP_ID_INT, new Integer(100));
+            }};           
+        createDocument("mv-alpha", rootFolderId, COMPLEX_TYPE, propertyMap1);
+
+        final List<String> mvProps2 = 
+            new ArrayList<String>() {
+            { 
+                add("red");
+                add("pink");
+                add("violet");
+            }};
+        
+        final Map<String, Object> propertyMap2 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_STRING_MULTI_VALUE, mvProps2);
+                put(PROP_ID_INT, new Integer(200));
+            }};           
+        createDocument("mv-beta", rootFolderId, COMPLEX_TYPE, propertyMap2);
+    }
     
     @SuppressWarnings("serial")
     public void createTestFolders() {
@@ -305,6 +340,7 @@ public class QueryTestDataCreator {
      * @param value
      * @return
      */
+    @SuppressWarnings("unchecked")
     private PropertyData<?> createPropertyData (String propId, Object value) {
         Class<?> clazz = value.getClass();
         if (clazz.equals(Boolean.class)) {
@@ -317,6 +353,20 @@ public class QueryTestDataCreator {
             return fFactory.createPropertyStringData(propId, (String)value);
         } else if (clazz.equals(GregorianCalendar.class)) {
             return fFactory.createPropertyDateTimeData(propId, (GregorianCalendar)value);
+        } else if (value instanceof List) {
+            clazz = ((List<?>)value).get(0).getClass();
+            if (clazz.equals(Boolean.class)) {
+                return fFactory.createPropertyBooleanData(propId, (List<Boolean>)value);
+            } else if (clazz.equals(Double.class)) {
+                return fFactory.createPropertyDecimalData(propId, (List<BigDecimal>)value);
+            } else if (clazz.equals(Integer.class)) {
+                return fFactory.createPropertyIntegerData(propId, (List<BigInteger>)value);
+            } else if (clazz.equals(String.class)) {
+                return fFactory.createPropertyStringData(propId, (List<String>)value);
+            } else if (clazz.equals(GregorianCalendar.class)) {
+                return fFactory.createPropertyDateTimeData(propId, (List<GregorianCalendar>)value);
+            } else
+                fail("unsupported type in propery value: " + clazz);
         } else
             fail("unsupported type in propery value: " + clazz);
         return null;