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;