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;