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/16 08:38:37 UTC
svn commit: r955139 - 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: Wed Jun 16 06:38:37 2010
New Revision: 955139
URL: http://svn.apache.org/viewvc?rev=955139&view=rev
Log:
CMIS-216
implement like, not like in in-memory
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/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/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=955139&r1=955138&r2=955139&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 Wed Jun 16 06:38:37 2010
@@ -26,6 +26,7 @@ import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
+import java.util.regex.Pattern;
import org.antlr.runtime.tree.Tree;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
@@ -35,6 +36,7 @@ import org.apache.chemistry.opencmis.com
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
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.impl.dataobjects.ObjectListImpl;
import org.apache.chemistry.opencmis.inmemory.TypeManager;
import org.apache.chemistry.opencmis.inmemory.query.QueryObject.SortSpec;
@@ -481,19 +483,38 @@ public class InMemoryQueryProcessor impl
}
private boolean evalWhereIsNull(StoredObject so, Tree node, Tree child) {
- throw new RuntimeException("Operator IS NULL not supported in InMemory server.");
+ Object propVal = getPropertyValue(child, so);
+ return null == propVal;
}
private boolean evalWhereIsNotNull(StoredObject so, Tree node, Tree child) {
- throw new RuntimeException("Operator IS NOT NULL not supported in InMemory server.");
+ Object propVal = getPropertyValue(child, so);
+ return null != propVal;
}
private boolean evalWhereIsLike(StoredObject so, Tree node, Tree colNode, Tree StringNode) {
- throw new RuntimeException("Operator LIKE not supported in InMemory server.");
+ Object rVal = onLiteral(StringNode);
+ if (!(rVal instanceof String))
+ throw new RuntimeException("LIKE operator requires String literal on right hand side.");
+
+ ColumnReference colRef = getColumnReference(colNode);
+ TypeDefinition td = colRef.getTypeDefinition();
+ PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+ PropertyType propType = pd.getPropertyType();
+ if (propType != PropertyType.STRING && propType != PropertyType.HTML && propType != PropertyType.ID &&
+ propType != PropertyType.URI)
+ throw new RuntimeException("Property type "+ propType.value() + " is not allowed FOR LIKE");
+ if (pd.getCardinality() != Cardinality.SINGLE)
+ throw new RuntimeException("LIKE is not allowed for multi-value properties ");
+
+ String propVal = (String) so.getProperties().get(colRef.getPropertyId()).getFirstValue();
+ String pattern = translatePattern((String) rVal); // SQL to Java regex syntax
+ Pattern p = Pattern.compile(pattern);
+ return p.matcher(propVal).matches();
}
private boolean evalWhereIsNotLike(StoredObject so, Tree node, Tree colNode, Tree stringNode) {
- throw new RuntimeException("Operator NOT LIKE not supported in InMemory server.");
+ return ! evalWhereIsLike(so, node, colNode, stringNode);
}
private boolean evalWhereContains(StoredObject so, Tree node, Tree colNode, Tree paramNode) {
@@ -508,13 +529,6 @@ public class InMemoryQueryProcessor impl
throw new RuntimeException("Operator IN_TREE not supported in InMemory server.");
}
- private void checkLiteral(Tree node) {
- int type = node.getType();
- if (type != CMISQLLexerStrict.BOOL_LIT && type != CMISQLLexerStrict.NUM_LIT || type != CMISQLLexerStrict.STRING_LIT
- || type != CMISQLLexerStrict.TIME_LIT)
- throw new RuntimeException("Literal expected.");
- }
-
private Object onLiteral(Tree node) {
int type = node.getType();
String text = node.getText();
@@ -539,24 +553,16 @@ public class InMemoryQueryProcessor impl
private Integer compareTo(StoredObject so, Tree leftChild, Tree rightChild) {
Object rVal = onLiteral(rightChild);
+
//log.debug("retrieve node from where: " + System.identityHashCode(leftChild) + " is " + leftChild);
- CmisSelector sel = queryObj.getColumnReference(leftChild.getTokenStartIndex());
- if (null == sel)
- throw new RuntimeException("Unknown property query name " + leftChild.getChild(0));
- else if (sel instanceof ColumnReference) {
- ColumnReference colRef = (ColumnReference) sel;
- TypeDefinition td = colRef.getTypeDefinition();
- PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
- PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
- if (null == lVal)
- return null; // property is not set
- else if (pd.getCardinality() == Cardinality.MULTI)
- throw new RuntimeException("You can't query operators <, <=, ==, !=, >=, > on multi-value properties ");
-
+ ColumnReference colRef = getColumnReference(leftChild);
+ TypeDefinition td = colRef.getTypeDefinition();
+ PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+ PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+ if (lVal instanceof List<?>)
+ throw new RuntimeException("You can't query operators <, <=, ==, !=, >=, > on multi-value properties ");
+ else
return compareTo(pd, lVal, rVal);
- } else {
- throw new RuntimeException("Unexpected numerical value function in where clause");
- }
}
private int compareTo(PropertyDefinition<?> td, PropertyData<?> lVal, Object rVal) {
@@ -611,6 +617,68 @@ public class InMemoryQueryProcessor impl
return 0;
}
+ private ColumnReference getColumnReference(Tree columnNode) {
+ CmisSelector sel = queryObj.getColumnReference(columnNode.getTokenStartIndex());
+ if (null == sel)
+ throw new RuntimeException("Unknown property query name " + columnNode.getChild(0));
+ else if (sel instanceof ColumnReference)
+ return (ColumnReference) sel;
+ else
+ throw new RuntimeException("Unexpected numerical value function in where clause");
+ }
+
+ private Object getPropertyValue(Tree columnNode, StoredObject so) {
+ ColumnReference colRef = getColumnReference(columnNode);
+ TypeDefinition td = colRef.getTypeDefinition();
+ PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+ PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+ if (null == lVal)
+ return null;
+ else {
+ if (pd.getCardinality() == Cardinality.SINGLE)
+ return null == lVal ? null : lVal.getFirstValue();
+ else
+ return lVal.getValues();
+ }
+ }
+
+ // translate SQL wildcards %, _ to Java regex syntax
+ public static String translatePattern(String wildcardString) {
+ int index = 0;
+ int start = 0;
+ StringBuffer res = new StringBuffer();
+
+ while (index >= 0) {
+ index = wildcardString.indexOf('%', start);
+ if (index < 0)
+ res.append(wildcardString.substring(start));
+ else if (index == 0 || index > 0 && wildcardString.charAt(index-1) != '\\') {
+ res.append(wildcardString.substring(start, index));
+ res.append(".*");
+ } else
+ res.append(wildcardString.substring(start, index+1));
+ start = index+1;
+ }
+ wildcardString = res.toString();
+
+ index = 0;
+ start = 0;
+ res = new StringBuffer();
+
+ while (index >= 0) {
+ index = wildcardString.indexOf('_', start);
+ if (index < 0)
+ res.append(wildcardString.substring(start));
+ else if (index == 0 || index > 0 && wildcardString.charAt(index-1) != '\\') {
+ res.append(wildcardString.substring(start, index));
+ res.append(".");
+ } else
+ res.append(wildcardString.substring(start, index+1));
+ start = index+1;
+ }
+ return res.toString();
+ }
+
private void throwIncompatibleTypesException(Object o1, Object o2) {
throw new RuntimeException("Incompatible Types to compare: " + o1 + " and " + o2);
}
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=955139&r1=955138&r2=955139&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 Wed Jun 16 06:38:37 2010
@@ -42,6 +42,7 @@ import org.junit.Test;
public class EvalQueryTest extends AbstractServiceTst {
private static Log log = LogFactory.getLog(EvalQueryTest.class);
+ private QueryTestDataCreator dataCreator;
@Before
public void setUp() throws Exception {
@@ -50,8 +51,8 @@ public class EvalQueryTest extends Abstr
super.setTypeCreatorClass(UnitTestTypeSystemCreator.class.getName());
super.setUp();
//create test data
- QueryTestDataCreator dataCreator = new QueryTestDataCreator(fRepositoryId, fRootFolderId, fObjSvc );
- dataCreator.createTestData();
+ dataCreator = new QueryTestDataCreator(fRepositoryId, fRootFolderId, fObjSvc );
+ dataCreator.createBasicTestData();
}
@After
@@ -470,6 +471,105 @@ public class EvalQueryTest extends Abstr
assertTrue(resultContainsAtPos("delta", 2, res) || resultContainsAtPos("delta", 1, res) || resultContainsAtPos("delta", 0, res));
}
+ @Test
+ public void testIsNull() {
+ dataCreator.createNullTestDocument();
+ String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + PROP_ID_INT + " IS NULL";
+ ObjectList res = doQuery(statement);
+ assertEquals(1, res.getObjects().size());
+ assertTrue(resultContains("nulldoc", res));
+ }
+
+ @Test
+ public void testIsNotNull() {
+ dataCreator.createNullTestDocument();
+ String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + PROP_ID_INT + " IS NOT NULL";
+ ObjectList 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 patternTest() {
+ String res = InMemoryQueryProcessor.translatePattern("ABC%def");
+ assertEquals("ABC.*def", res);
+ res = InMemoryQueryProcessor.translatePattern("%abc");
+ assertEquals(".*abc", res);
+ res = InMemoryQueryProcessor.translatePattern("abc%");
+ assertEquals("abc.*", res);
+ res = InMemoryQueryProcessor.translatePattern("ABC\\%def");
+ assertEquals("ABC\\%def", res);
+ res = InMemoryQueryProcessor.translatePattern("\\%abc");
+ assertEquals("\\%abc", res);
+ res = InMemoryQueryProcessor.translatePattern("abc%def%ghi");
+ assertEquals("abc.*def.*ghi", res);
+ res = InMemoryQueryProcessor.translatePattern("abc%def\\%ghi%jkl");
+ assertEquals("abc.*def\\%ghi.*jkl", res);
+
+ res = InMemoryQueryProcessor.translatePattern("ABC_def");
+ assertEquals("ABC.def", res);
+ res = InMemoryQueryProcessor.translatePattern("_abc");
+ assertEquals(".abc", res);
+ res = InMemoryQueryProcessor.translatePattern("abc_");
+ assertEquals("abc.", res);
+ res = InMemoryQueryProcessor.translatePattern("ABC\\_def");
+ assertEquals("ABC\\_def", res);
+ res = InMemoryQueryProcessor.translatePattern("\\_abc");
+ assertEquals("\\_abc", res);
+ res = InMemoryQueryProcessor.translatePattern("abc_def_ghi");
+ assertEquals("abc.def.ghi", res);
+ res = InMemoryQueryProcessor.translatePattern("abc_def\\_ghi_jkl");
+ assertEquals("abc.def\\_ghi.jkl", res);
+ }
+
+ @Test
+ public void testLike() {
+ dataCreator.createLikeTestDocuments();
+ String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " LIKE 'ABC%'";
+ ObjectList res = doQuery(statement);
+ assertEquals(2, res.getObjects().size());
+ assertTrue(resultContains("likedoc1", res));
+ assertTrue(resultContains("likedoc2", res));
+
+ statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " LIKE '%ABC'";
+ res = doQuery(statement);
+ assertEquals(1, res.getObjects().size());
+ assertTrue(resultContains("likedoc3", res));
+
+ statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " LIKE '%ABC%'";
+ res = doQuery(statement);
+ assertEquals(3, res.getObjects().size());
+ assertTrue(resultContains("likedoc1", res));
+ assertTrue(resultContains("likedoc2", res));
+ assertTrue(resultContains("likedoc3", res));
+
+ statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " LIKE 'AB_DEF'";
+ res = doQuery(statement);
+ assertEquals(1, res.getObjects().size());
+ assertTrue(resultContains("likedoc1", res));
+ }
+
+ @Test
+ public void testNotLike() {
+ dataCreator.createLikeTestDocuments();
+ String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " NOT LIKE 'ABC%'";
+ ObjectList res = doQuery(statement);
+ assertEquals(6, res.getObjects().size());
+ assertTrue(resultContains("likedoc3", res));
+
+ statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + UnitTestTypeSystemCreator.PROP_ID_STRING + " NOT LIKE '%a'";
+ res = doQuery(statement);
+ assertEquals(4, res.getObjects().size());
+ assertTrue(resultContains("likedoc1", res));
+ assertTrue(resultContains("likedoc1", res));
+ assertTrue(resultContains("likedoc3", res));
+ assertTrue(resultContains("epsilon", res));
+ }
+
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=955139&r1=955138&r2=955139&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 Wed Jun 16 06:38:37 2010
@@ -80,13 +80,13 @@ public class QueryTestDataCreator {
fObjSvc = objSvc;
}
- public void createTestData() {
+ public void createBasicTestData() {
createTestFolders();
- createTestDocuments();
+ createBasicTestDocuments();
}
@SuppressWarnings("serial")
- public void createTestDocuments() {
+ public void createBasicTestDocuments() {
final GregorianCalendar gc1 = new GregorianCalendar(TZ);
gc1.clear();
@@ -188,7 +188,42 @@ public class QueryTestDataCreator {
folder11 = createFolder("Folder 11", folder1, FOLDER_TYPE, propertyMap3);
}
+ @SuppressWarnings("serial")
+ public void createNullTestDocument() {
+ final Map<String, Object> propertyMap1 =
+ new HashMap<String, Object>() {
+ {
+ put(PROP_ID_STRING, "DocumentWithNulls");
+ }};
+ createDocument("nulldoc", rootFolderId, COMPLEX_TYPE, propertyMap1);
+ }
+
+ @SuppressWarnings("serial")
+ public void createLikeTestDocuments() {
+
+ final Map<String, Object> propertyMap1 =
+ new HashMap<String, Object>() {
+ {
+ put(PROP_ID_STRING, "ABCDEF");
+ }};
+ createDocument("likedoc1", rootFolderId, COMPLEX_TYPE, propertyMap1);
+
+ final Map<String, Object> propertyMap2 =
+ new HashMap<String, Object>() {
+ {
+ put(PROP_ID_STRING, "ABC123");
+ }};
+ createDocument("likedoc2", rootFolderId, COMPLEX_TYPE, propertyMap2);
+
+ final Map<String, Object> propertyMap3 =
+ new HashMap<String, Object>() {
+ {
+ put(PROP_ID_STRING, "123ABC");
+ }};
+ createDocument("likedoc3", rootFolderId, COMPLEX_TYPE, propertyMap3);
+ }
+
private String createFolder(String folderName, String parentFolderId, String typeId, Map<String, Object> properties) {
Properties props = createFolderProperties(folderName, typeId, properties);
String id = null;