Added: 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=954587&view=auto ============================================================================== --- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java (added) +++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java Mon Jun 14 18:51:24 2010 @@ -0,0 +1,279 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.chemistry.opencmis.inmemory.query; + +import static org.junit.Assert.fail; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.data.Acl; +import org.apache.chemistry.opencmis.commons.data.ContentStream; +import org.apache.chemistry.opencmis.commons.data.ExtensionsData; +import org.apache.chemistry.opencmis.commons.data.Properties; +import org.apache.chemistry.opencmis.commons.data.PropertyData; +import org.apache.chemistry.opencmis.commons.enums.VersioningState; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.BindingsObjectFactoryImpl; +import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory; +import org.apache.chemistry.opencmis.commons.spi.ObjectService; +import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.*; + +/** + * Utility class that fills the in-memory repository with some test objects that + * can be used for query + * + * @author Jens + * + * This class uses the following data for query testing. We have one document type + * "ComplexType" and one folder type "FolderType" The document type has one property of + * each of the types boolean, integer, decimal, string and datetime. id, uri and html are + * treated like a string and do not make a difference. + * + * String Int Double DateTime Boolean + * ------------------------------------------------ + * Alpha -100 -1.6E-5 23.05.1618 true + * Beta -50 -4.0E24 08.05.1945 false + * Gamma 0 3.141592 (now) true + * Delta 50 1.23456E-6 20.01.2038 true + * Epsilon 100 1.2345E12 14.07.2345 false + * + * For folder and tree tests this series is put in each of the three test folders + */ +public class QueryTestDataCreator { + + private BindingsObjectFactory fFactory = new BindingsObjectFactoryImpl(); + private String rootFolderId; + private String repositoryId; + private ObjectService fObjSvc; + private String doc1, doc2, doc3, doc4, doc5; + private String folder1; + private String folder2; + private String folder11; + private static final TimeZone TZ = TimeZone.getTimeZone("Zulu"); + + public QueryTestDataCreator(String repositoryId, String rootFolderId, ObjectService objSvc) { + this.rootFolderId = rootFolderId; + this.repositoryId = repositoryId; + fObjSvc = objSvc; + } + + public void createTestData() { + createTestFolders(); + createTestDocuments(); + } + + @SuppressWarnings("serial") + public void createTestDocuments() { + + final GregorianCalendar gc1 = new GregorianCalendar(TZ); + gc1.clear(); + gc1.set(1945, 4, 8); + + final Map<String, Object> propertyMap1 = + new HashMap<String, Object>() { + { + put(PROP_ID_STRING, "Alpha"); + put(PROP_ID_INT, new Integer(-100)); + put(PROP_ID_DECIMAL, new Double(-4.0E24d)); + put(PROP_ID_DATETIME, gc1); + put(PROP_ID_BOOLEAN, true); + }}; + doc1 = createDocument("alpha", rootFolderId, COMPLEX_TYPE, propertyMap1); + + final GregorianCalendar gc2 = new GregorianCalendar(TZ); + gc2.clear(); + gc2.set(1618, 4, 23); + + final Map<String, Object> propertyMap2 = + new HashMap<String, Object>() { + { + put(PROP_ID_STRING, "Beta"); + put(PROP_ID_INT, new Integer(-50)); + put(PROP_ID_DECIMAL, new Double(-1.6E-5d)); + put(PROP_ID_DATETIME, gc2); + put(PROP_ID_BOOLEAN, false); + }}; + doc2 = createDocument("beta", rootFolderId, COMPLEX_TYPE, propertyMap2); + + final Map<String, Object> propertyMap3 = + new HashMap<String, Object>() { + { + put(PROP_ID_STRING, "Gamma"); + put(PROP_ID_INT, new Integer(0)); + put(PROP_ID_DECIMAL, new Double(Math.PI)); + put(PROP_ID_DATETIME, new GregorianCalendar(TZ)); + put(PROP_ID_BOOLEAN, true); + }}; + doc3 = createDocument("gamma", rootFolderId, COMPLEX_TYPE, propertyMap3); + + final GregorianCalendar gc4 = new GregorianCalendar(TZ); + gc4.clear(); + gc4.set(2038, 0, 20); + + final Map<String, Object> propertyMap4 = + new HashMap<String, Object>() { + { + put(PROP_ID_STRING, "Delta"); + put(PROP_ID_INT, new Integer(50)); + put(PROP_ID_DECIMAL, new Double(1.23456E-6)); + put(PROP_ID_DATETIME, gc4); + put(PROP_ID_BOOLEAN, true); + }}; + doc4 = createDocument("delta", rootFolderId, COMPLEX_TYPE, propertyMap4); + + final GregorianCalendar gc5 = new GregorianCalendar(TZ); + gc5.clear(); + gc5.set(2345, 6, 14); + + final Map<String, Object> propertyMap5 = + new HashMap<String, Object>() { + { + put(PROP_ID_STRING, "Epsilon"); + put(PROP_ID_INT, new Integer(100)); + put(PROP_ID_DECIMAL, new Double(1.2345E12)); + put(PROP_ID_DATETIME, gc5); + put(PROP_ID_BOOLEAN, false); + }}; + doc5 = createDocument("epsilon", rootFolderId, COMPLEX_TYPE, propertyMap5); + +} + + @SuppressWarnings("serial") + public void createTestFolders() { + final Map<String, Object> propertyMap1 = + new HashMap<String, Object>() { + { + put(PROP_ID_INT, new Integer(1234)); + put(PROP_ID_STRING, "ABCD"); + }}; + folder1 = createFolder("Folder 1", rootFolderId, FOLDER_TYPE, propertyMap1); + + final Map<String, Object> propertyMap2 = + new HashMap<String, Object>() { + { + put(PROP_ID_INT, new Integer(-2345)); + put(PROP_ID_STRING, "defg"); + }}; + folder2 = createFolder("Folder 2", rootFolderId, FOLDER_TYPE, propertyMap2); + + final Map<String, Object> propertyMap3 = + new HashMap<String, Object>() { + { + put(PROP_ID_INT, new Integer(123)); + put(PROP_ID_STRING, "ZZZZ"); + }}; + folder11 = createFolder("Folder 11", folder1, FOLDER_TYPE, propertyMap3); + } + + + private String createFolder(String folderName, String parentFolderId, String typeId, Map<String, Object> properties) { + Properties props = createFolderProperties(folderName, typeId, properties); + String id = null; + try { + id = fObjSvc.createFolder(repositoryId, props, parentFolderId, null, null, null, null); + if (null == id) + fail("createFolder failed."); + } catch (Exception e) { + fail("createFolder() failed with exception: " + e); + } + return id; + } + + private String createDocument(String name, String folderId, String typeId, Map<String, Object> properties) { + ContentStream contentStream = null; + List<String> policies = null; + Acl addACEs = null; + Acl removeACEs = null; + ExtensionsData extension = null; + + Properties props = createDocumentProperties(name, typeId, properties); + + String id = null; + try { + id = fObjSvc.createDocument(repositoryId, props, folderId, contentStream, VersioningState.NONE, policies, + addACEs, removeACEs, extension); + if (null == id) + fail("createDocument failed."); + } catch (Exception e) { + fail("createDocument() failed with exception: " + e); + } + return id; + + } + + private Properties createDocumentProperties(String name, String typeId, Map<String, Object> propertyMap) { + List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>(); + properties.add(fFactory.createPropertyIdData(PropertyIds.NAME, name)); + properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, typeId)); + for (Map.Entry<String,Object> propEntry :propertyMap.entrySet()) { + PropertyData<?> pd = + createPropertyData(propEntry.getKey(), propEntry.getValue()); + properties.add(pd); + } + Properties props = fFactory.createPropertiesData(properties); + return props; + } + + private Properties createFolderProperties(String folderName, String typeId, Map<String, Object> propertyMap) { + List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>(); + properties.add(fFactory.createPropertyIdData(PropertyIds.NAME, folderName)); + properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, typeId)); + for (Map.Entry<String,Object> propEntry :propertyMap.entrySet()) { + PropertyData<?> pd = + createPropertyData(propEntry.getKey(), propEntry.getValue()); + properties.add(pd); + } + Properties props = fFactory.createPropertiesData(properties); + return props; + } + + + /** + * Simplified property creation method, create Property of Boolean, String, Integer, + * Decimal, or DataTime depending on class of value (Boolean, String, Integer, Double, + * or GregorianCalendar. Id, Html and URI are not supported + * + * @param propId + * @param value + * @return + */ + private PropertyData<?> createPropertyData (String propId, Object value) { + Class<?> clazz = value.getClass(); + if (clazz.equals(Boolean.class)) { + return fFactory.createPropertyBooleanData(propId, (Boolean)value); + } else if (clazz.equals(Double.class)) { + return fFactory.createPropertyDecimalData(propId, BigDecimal.valueOf((Double)value)); + } else if (clazz.equals(Integer.class)) { + return fFactory.createPropertyIntegerData(propId, BigInteger.valueOf((Integer)value)); + } else if (clazz.equals(String.class)) { + return fFactory.createPropertyStringData(propId, (String)value); + } else if (clazz.equals(GregorianCalendar.class)) { + return fFactory.createPropertyDateTimeData(propId, (GregorianCalendar)value); + } else + fail("unsupported type in propery value: " + clazz); + return null; + } +}
Added: incubator/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/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java?rev=954587&view=auto ============================================================================== --- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java (added) +++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java Mon Jun 14 18:51:24 2010 @@ -0,0 +1,422 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.chemistry.opencmis.inmemory.query; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; +import java.util.Map; + +import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; +import org.apache.chemistry.opencmis.inmemory.TypeManagerImpl; +import org.apache.chemistry.opencmis.inmemory.query.CmisQueryWalker; +import org.apache.chemistry.opencmis.inmemory.query.CmisSelector; +import org.apache.chemistry.opencmis.inmemory.query.ColumnReference; +import org.apache.chemistry.opencmis.inmemory.query.QueryObject; +import org.apache.chemistry.opencmis.inmemory.query.QueryObject.SortSpec; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class QueryTypesTest extends AbstractQueryTest { + + private TypeManagerImpl tm; + + @Before + public void setUp() throws Exception { + tm = new TypeManagerImpl(); + tm.initTypeSystem(null); // create CMIS default types + + // create some types for testing + List<TypeDefinition> typeDefs = super.createTypes(); + for (TypeDefinition typeDef : typeDefs) + tm.addTypeDefinition(typeDef); + + // initialize query object with type manager + super.setUp(new QueryObject(tm, null)); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void resolveTypesTest1() throws Exception { + String statement = "SELECT " + TITLE_PROP + ", " + AUTHOR_PROP + " FROM " + BOOK_TYPE + " AS BooksAlias WHERE " + ISBN_PROP + " = '100'"; + verifyResolveSelect(statement); + } + + @Test + public void resolveTypesTest2() throws Exception { + String statement = "SELECT BookType.Title, BookType.Author FROM BookType WHERE ISBN = '100'"; + verifyResolveSelect(statement); + } + + @Test + public void resolveTypesTest3() throws Exception { + String statement = "SELECT BookType.Title, BookType.Author FROM BookType AS BooksAlias WHERE ISBN = '100'"; + verifyResolveSelect(statement); + } + + @Test + public void resolveTypesTest4() throws Exception { + String statement = "SELECT BooksAlias.Title, BooksAlias.Author FROM BookType AS BooksAlias WHERE ISBN = '100'"; + verifyResolveSelect(statement); + } + + @Test + public void resolveTypesTest5() throws Exception { + String statement = "SELECT BooksAlias.Title AS abc, BooksAlias.Author def FROM BookType AS BooksAlias WHERE ISBN = '100'"; + verifyResolveSelect(statement); + } + + @Test + public void resolveTypesTest6() throws Exception { + String statement = "SELECT BookType.UnknownProperty FROM BookType WHERE ISBN = '100'"; + try { + verifyResolveSelect(statement); + fail("Select of unknown property in type should fail."); + } catch (Exception e) { + assertTrue(e instanceof CmisInvalidArgumentException); + assertTrue(e.getMessage().contains("is not a valid property query name in")); + } + } + + @Test + public void resolveTypesTest7() throws Exception { + String statement = "SELECT UnknownProperty FROM BookType WHERE ISBN = '100'"; + try { + verifyResolveSelect(statement); + fail("Select of unknown property in type should fail."); + } catch (Exception e) { + assertTrue(e instanceof CmisInvalidArgumentException); + assertTrue(e.getMessage().contains("is not a property query name in any")); + } + } + + @Test + public void resolveTypesTest8() throws Exception { + String statement = "SELECT BookType.Title, BookType.Author FROM BookType WHERE ISBN = '100'"; + verifyResolveSelect(statement); + } + + @Test + public void resolveTypesTest9() throws Exception { + String statement = "SELECT BookType.Author, Title TitleAlias FROM BookType WHERE TitleAlias <> 'Harry Potter'"; + verifyResolveSelect(statement); + } + + @Test + public void resolveTypesTest10() throws Exception { + String statement = "SELECT BookType.Author, BookType.Title TitleAlias FROM BookType WHERE TitleAlias <> 'Harry Potter'"; + verifyResolveSelect(statement); + } + + private void verifyResolveSelect(String statement) throws Exception { + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + Map<String,String> types = qo.getTypes(); + assertTrue(1 == types.size()); + List<CmisSelector> selects = qo.getSelectReferences(); + assertTrue(2 == selects.size()); + for (CmisSelector select : selects) { + assertTrue(select instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) select); + assertEquals(bookType, colRef.getTypeDefinition()); + assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP) || colRef.getPropertyQueryName().equals(AUTHOR_PROP)); + } + } + + @Test + public void resolveTypesWithTwoFromsQualified() throws Exception { + String statement = "SELECT BookType.Title, MyDocType.MyStringProp FROM BookType JOIN MyDocType WHERE BookType.ISBN = '100'"; + + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + Map<String,String> types = qo.getTypes(); + assertTrue(2 == types.size()); + List<CmisSelector> selects = qo.getSelectReferences(); + assertTrue(2 == selects.size()); + + ColumnReference colRef = ((ColumnReference) selects.get(0)); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP)); + + colRef = ((ColumnReference) selects.get(1)); + assertEquals(colRef.getTypeDefinition(), myType); + assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP)); + } + + @Test + public void resolveTypesWithTwoFromsUnqualified() throws Exception { + String statement = "SELECT Title, MyStringProp FROM BookType JOIN MyDocType AS MyDocAlias WHERE BookType.ISBN = '100'"; + + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + Map<String,String> types = qo.getTypes(); + assertTrue(2 == types.size()); + List<CmisSelector> selects = qo.getSelectReferences(); + assertTrue(2 == selects.size()); + + ColumnReference colRef = ((ColumnReference) selects.get(0)); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP)); + + colRef = ((ColumnReference) selects.get(1)); + assertEquals(colRef.getTypeDefinition(), myType); + assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP)); + } + + @Test + public void resolveTypesWithTwoFromsNotUnique() throws Exception { + String statement = "SELECT MyStringProp FROM MyDocTypeCopy JOIN MyDocType"; + + try { + traverseStatement(statement); + fail("Select with an unqualified property that is not unique should fail."); + } catch (Exception e) { + assertTrue(e instanceof CmisInvalidArgumentException); + assertTrue(e.getMessage().contains("is not a unique property query name within the types in from")); + } + } + + @Test + public void resolveTypesWithTwoFromsUniqueByQualifying() throws Exception { + String statement = "SELECT MyDocType.MyStringProp FROM MyDocTypeCopy JOIN MyDocType"; + + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + Map<String,String> types = qo.getTypes(); + assertTrue(2 == types.size()); + List<CmisSelector> selects = qo.getSelectReferences(); + assertTrue(1 == selects.size()); + ColumnReference colRef = ((ColumnReference) selects.get(0)); + assertEquals(myType, colRef.getTypeDefinition()); + assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP)); + } + + @Test + public void resolveTypesTest11() throws Exception { + String statement = "SELECT BookType.* FROM BookType WHERE ISBN = '100'"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + Map<String,String> types = qo.getTypes(); + assertTrue(1 == types.size()); + List<CmisSelector> selects = qo.getSelectReferences(); + assertTrue(1 == selects.size()); + ColumnReference colRef = ((ColumnReference) selects.get(0)); + assertTrue(colRef.getPropertyQueryName().equals("*")); + assertEquals(bookType, colRef.getTypeDefinition()); + } + + @Test + public void resolveTypesTest12() throws Exception { + String statement = "SELECT * FROM MyDocTypeCopy JOIN MyDocType"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + Map<String,String> types = qo.getTypes(); + assertTrue(2 == types.size()); + List<CmisSelector> selects = qo.getSelectReferences(); + assertTrue(1 == selects.size()); + ColumnReference colRef = ((ColumnReference) selects.get(0)); + assertTrue(colRef.getPropertyQueryName().equals("*")); + assertEquals(null, colRef.getTypeDefinition()); + } + + @Test + public void resolveTypesWhere1() throws Exception { + String statement = "SELECT * FROM BookType WHERE ISBN = '100'"; + verifyResolveWhere(statement); + } + + @Test + public void resolveTypesWhere2() throws Exception { + String statement = "SELECT * FROM BookType WHERE BookType.ISBN = '100'"; + verifyResolveWhere(statement); + } + + @Test + public void resolveTypesWhere3() throws Exception { + String statement = "SELECT * FROM BookType As BookAlias WHERE BookAlias.ISBN = '100'"; + verifyResolveWhere(statement); + } + + @Test + public void resolveTypesWhere4() throws Exception { + String statement = "SELECT BookType.ISBN IsbnAlias FROM BookType WHERE IsbnAlias < '100'"; + verifyResolveWhere(statement); + } + + @Test + public void resolveTypesWhereWithTwoFromsUnqualified() throws Exception { + String statement = "SELECT * FROM BookType JOIN MyDocType WHERE ISBN = '100'"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<CmisSelector> wheres = qo.getWhereReferences(); + assertTrue(1 == wheres.size()); + for (CmisSelector where : wheres) { + assertTrue(where instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) where); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP)); + } + } + + @Test + public void resolveTypesWhereWithTwoFromsQualified() throws Exception { + String statement = "SELECT * FROM BookType JOIN MyDocType AS MyDocAlias WHERE BookType.ISBN = '100'"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<CmisSelector> wheres = qo.getWhereReferences(); + assertTrue(1 == wheres.size()); + for (CmisSelector where : wheres) { + assertTrue(where instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) where); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP)); + } + } + + + @Test + public void resolveTypesWhereWithTwoFromsQualifiedWithAlias() throws Exception { + String statement = "SELECT * FROM BookType AS MyBookAlias JOIN MyDocType WHERE MyBookAlias.ISBN = '100'"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<CmisSelector> wheres = qo.getWhereReferences(); + assertTrue(1 == wheres.size()); + for (CmisSelector where : wheres) { + assertTrue(where instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) where); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP)); + } + } + + private void verifyResolveWhere(String statement) throws Exception { + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + Map<String,String> types = qo.getTypes(); + assertTrue(1 == types.size()); + List<CmisSelector> wheres = qo.getWhereReferences(); + assertTrue(1 == wheres.size()); + for (CmisSelector where : wheres) { + assertTrue(where instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) where); + assertEquals(bookType, colRef.getTypeDefinition()); + assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP)); + } + } + + @Test + public void resolveTypesWhereWithTwoFromsNotUnique() throws Exception { + String statement = "SELECT * FROM MyDocTypeCopy JOIN MyDocType WHERE MyStringProp = '100'"; + + try { + CmisQueryWalker walker = traverseStatement(statement); + fail("Select with an unqualified property that is not unique should fail."); + } catch (Exception e) { + assertTrue(e instanceof CmisInvalidArgumentException); + assertTrue(e.getMessage().contains("is not a unique property query name within the types in from")); + } + } + + @Test + public void resolveTypesWhereWithTwoFromsUniqueByQualifying() throws Exception { + String statement = "SELECT * FROM MyDocTypeCopy JOIN MyDocType WHERE MyDocType.MyStringProp = '100'"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<CmisSelector> wheres = qo.getWhereReferences(); + assertTrue(1 == wheres.size()); + for (CmisSelector where : wheres) { + assertTrue(where instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) where); + assertEquals(colRef.getTypeDefinition(), myType); + assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP)); + } + } + + @Test + public void resolveTypesOrderBy() throws Exception { + String statement = "SELECT Title AS TitleAlias FROM BookType WHERE Author = 'Jim' ORDER BY TitleAlias"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<SortSpec> sorts = qo.getOrderBys(); + assertTrue(1 == sorts.size()); + for (SortSpec sort : sorts) { + assertTrue(sort.getSelector() instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) sort.getSelector()); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP)); + } + } + + @Test + public void resolveTypesOrderBy2() throws Exception { + String statement = "SELECT Title AS TitleAlias FROM BookType WHERE Author = 'Jim' ORDER BY BookType.Author"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<SortSpec> sorts = qo.getOrderBys(); + assertTrue(1 == sorts.size()); + for (SortSpec sort : sorts) { + assertTrue(sort.getSelector() instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) sort.getSelector()); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(AUTHOR_PROP)); + } + } + + @Test + public void resolveTypesOrderBy3() throws Exception { + String statement = "SELECT Title FROM BookType WHERE ISBN < '100' ORDER BY Author"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<SortSpec> sorts = qo.getOrderBys(); + assertTrue(1 == sorts.size()); + for (SortSpec sort : sorts) { + assertTrue(sort.getSelector() instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) sort.getSelector()); + assertEquals(colRef.getTypeDefinition(), bookType); + assertTrue(colRef.getPropertyQueryName().equals(AUTHOR_PROP)); + } + } + + @Test + public void resolveJoinTypesSimple() throws Exception { + String statement = "SELECT * FROM MyDocType JOIN BookType ON MyDocType.MyStringProp = BookType.Title"; + CmisQueryWalker walker = traverseStatement(statement); + QueryObject qo = walker.queryObj; + List<CmisSelector> joins = qo.getJoinReferences(); + assertTrue(2 == joins.size()); + for (CmisSelector join : joins) { + assertTrue(join instanceof ColumnReference); + ColumnReference colRef = ((ColumnReference) join); + if (myType.equals(colRef.getTypeDefinition())) { + assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP)); + } else if (bookType.equals(colRef.getTypeDefinition())) { + assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP)); + } else + fail("Unexpected type in JOIN reference"); + } + } + +}
