blob: 96ca8366254896bc0145c6e1e2767a704f80669c [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
/*
* IndexCreationJUnitTest.java
*
* Created on April 13, 2005, 4:16 PM
* Added a Test Case for testing the Task, IUM10 : May 16, 2005, 2:45 PM
*/
/**
* @author vikramj
*/
package com.gemstone.gemfire.cache.query.functional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import com.gemstone.gemfire.cache.AttributesFactory;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.query.CacheUtils;
import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.query.IndexStatistics;
import com.gemstone.gemfire.cache.query.IndexType;
import com.gemstone.gemfire.cache.query.Query;
import com.gemstone.gemfire.cache.query.QueryInvalidException;
import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.cache.query.SelectResults;
import com.gemstone.gemfire.cache.query.Utils;
import com.gemstone.gemfire.cache.query.data.ComparableWrapper;
import com.gemstone.gemfire.cache.query.data.Portfolio;
import com.gemstone.gemfire.cache.query.internal.DefaultQueryService;
import com.gemstone.gemfire.cache.query.internal.QueryObserverAdapter;
import com.gemstone.gemfire.cache.query.internal.QueryObserverHolder;
import com.gemstone.gemfire.cache.query.internal.index.CompactMapRangeIndex;
import com.gemstone.gemfire.cache.query.internal.index.CompactRangeIndex;
import com.gemstone.gemfire.cache.query.internal.index.IndexProtocol;
import com.gemstone.gemfire.cache.query.internal.index.RangeIndex;
import com.gemstone.gemfire.cache.query.internal.types.ObjectTypeImpl;
import com.gemstone.gemfire.cache.query.internal.types.StructTypeImpl;
import com.gemstone.gemfire.cache.query.types.ObjectType;
import com.gemstone.gemfire.cache.query.types.StructType;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.AvailablePort;
import com.gemstone.gemfire.internal.FileUtil;
import com.gemstone.gemfire.internal.cache.LocalRegion;
import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
@Category(IntegrationTest.class)
public class IndexCreationJUnitTest{
ObjectType resType1=null;
ObjectType resType2= null;
int resSize1=0;
int resSize2=0;
Iterator itert1=null;
Iterator itert2=null;
Set set1=null;
Set set2=null;
String s1;
String s2;
@Before
public void setUp() throws java.lang.Exception {
CacheUtils.startCache();
Region region = CacheUtils.createRegion("portfolios", Portfolio.class);
for(int i=0;i<4;i++){
region.put(""+i, new Portfolio(i));
// CacheUtils.log(new Portfolio(i));
}
}
@After
public void tearDown() throws java.lang.Exception {
CacheUtils.closeCache();
}
@Test
public void testIndexCreation() throws Exception {
QueryService qs;
qs = CacheUtils.getQueryService();
Index i1 = qs.createIndex("statusIndex", IndexType.FUNCTIONAL,"status","/portfolios, positions");
//TASK ICM1
Index i2 = qs.createIndex("secIdIndex", IndexType.FUNCTIONAL,"b.secId","/portfolios pf, pf.positions.values b");
//TASK ICM2
Index i5= qs.createIndex("intFunctionIndex", IndexType.FUNCTIONAL,"intFunction(pf.getID)","/portfolios pf, pf.positions b");
Index i6 = qs.createIndex("statusIndex6", IndexType.FUNCTIONAL,"a.status","/portfolios.values.toArray a, positions");
Index i7 = qs.createIndex("statusIndex7", IndexType.FUNCTIONAL,"a.status","/portfolios.getValues().asList() a, positions");
Index i8 = qs.createIndex("statusIndex8", IndexType.FUNCTIONAL,"a.status","/portfolios.values.asSet a, positions");
//TASK ICM6
Object indices[]={i1,i2,i5,i6,i7,i8}; //remove any commented Index
// from Array
for(int j=0;j<indices.length;j++){
CacheUtils.log(((IndexProtocol)indices[j]).isValid());
boolean r = ((IndexProtocol)indices[j]).isValid();
assertTrue("Test: testIndexCreation FAILED", r);
CacheUtils.log(((IndexProtocol)indices[j]).getName());
CacheUtils.log("Test: testIndexCreation PASS");
}
}
@Test
public void testIndexCreationWithImports() throws Exception {
// Task ID ICM 16
QueryService qs;
qs = CacheUtils.getQueryService();
Index idx;
try {
idx = qs.createIndex("importsIndex", IndexType.FUNCTIONAL, "status",
"/portfolios, (map<string,Position>)positions");
fail("Should have thrown a QueryInvalidException"); // can't find type
// Position
} catch (QueryInvalidException e) {
// pass
}
idx = qs.createIndex("importsIndex", IndexType.FUNCTIONAL, "status",
"/portfolios, (map<string,Position>)positions",
"import com.gemstone.gemfire.cache.\"query\".data.Position");
qs.removeIndex(idx);
idx = qs.createIndex("importsIndex2", IndexType.FUNCTIONAL, "status",
"/portfolios, positions TYPE Position",
"import com.gemstone.gemfire.cache.\"query\".data.Position");
}
@Test
public void testSimilarIndexCreation() throws Exception {
// Task ID: ICM17
QueryService qs;
qs = CacheUtils.getQueryService();
// boolean exceptionoccured = true;
qs.createIndex("statusIndex", IndexType.FUNCTIONAL,"status","/portfolios, positions");
qs.createIndex("secIdIndex", IndexType.FUNCTIONAL,"b.secId","/portfolios pf, pf.positions.values b");
try {
qs.createIndex("secIdIndexDuplicate", IndexType.FUNCTIONAL,"b.secId","/portfolios pf, pf.positions.values b");
fail("testSimilarIndexCreation: Allowed duplicate index creation");
} catch (Exception e) {
// testSimilarIndexCreation: Exception if duplicate index is
// created with diffrenet name but same from clause & expression
}
try {
qs.createIndex("secIdIndexDuplicate", IndexType.FUNCTIONAL,"b1.secId","/portfolios pf1, pf1.positions.values b1");
fail("testSimilarIndexCreation: Allowed duplicate index creation");
} catch ( Exception e) {
// testSimilarIndexCreation: Exception if duplicate index is
// created with diffrenet name but same from clause & expression
}
//com.gemstone.gemfire.cache.query.IndexExistsException: Similar Index
// Exists
try {
qs.createIndex("statusIndexDuplicate", IndexType.FUNCTIONAL,"b.status","/portfolios b, positions");
fail("testSimilarIndexCreation: Allowed duplicate index creation");
} catch ( Exception e) {
// testSimilarIndexCreation: Exception if duplicate index is
// created with diffrenet name but same from clause & expression
}
}
@Test
public void testInvalidImportsIndexCreation() throws Exception {
// Task ID: Invalid Indexes: ICM15
QueryService qs;
qs = CacheUtils.getQueryService();
try{
qs.createIndex("typeIndex", IndexType.FUNCTIONAL,"\"type\"","/portfolios pf, pf.positions b","pf.position1");
// projection attributes are not yet implemented
// last parameter is the imports statement, so this is a syntax
// error
fail("Should have thrown an exception since imports are invalid");
//TASK ICM7
} catch (QueryInvalidException e){
// pass
}
}
public void _BUGtestElementIndexCreation() throws Exception {
QueryService qs;
qs = CacheUtils.getQueryService();
try{
qs.createIndex("funcReturnSecIdIndex", IndexType.FUNCTIONAL,"pf.funcReturnSecId(element(select distinct pos from /portfolios pf, pf.positions.values as pos where pos.sharesOutstanding = 5000))","/portfolios pf, pf.positions b");
//TASK ICM8: InvalidIndexCreation
// Query q = qs.newQuery("(element(select distinct pos from
// /portfolios pf, pf.positions.values as pos where
// pos.sharesOutstanding = 5000))");
// Object r=q.execute();
// CacheUtils.log(Utils.printResult(r));
} catch (Exception e){
e.printStackTrace();
fail("Test Case:testElementIndexCreation FAILED");
}
}
@Test
public void testIndexCreationOnNVLFunction() {
QueryService qs;
qs = CacheUtils.getQueryService();
Query query = null;
// Object result = null;
try {
qs.createIndex("NVLIndex1",IndexType.FUNCTIONAL, "nvl(pf.position2, pf.position1).secId", "/portfolios pf");
query = CacheUtils.getQueryService().newQuery("select distinct * from /portfolios pf where nvl(pf.position2, pf.position1).secId = 'SUN'");
QueryObserverImpl observer = new QueryObserverImpl();
QueryObserverHolder.setInstance(observer);
query.execute();
if(!observer.isIndexesUsed){
fail("NO INDEX USED");
}
query = CacheUtils.getQueryService().newQuery("select distinct nvl(pf.position2, 'inProjection') from /portfolios pf where nvl(pf.position2, pf.position1).secId = 'SUN'");
observer = new QueryObserverImpl();
QueryObserverHolder.setInstance(observer);
query.execute();
if(!observer.isIndexesUsed && observer.indexesUsed.size() != 1){
fail("NO INDEX USED");
}
} catch (Exception e) {
e.printStackTrace();
fail("Test Case:testElementIndexCreation FAILED");
}
}
@Test
public void testIndexCreationWithImport() throws Exception {
// Task ID: ICM16
QueryService qs;
qs = CacheUtils.getQueryService();
Index i3 = qs.createIndex("typeIndex", IndexType.FUNCTIONAL,"\"type\"","/portfolios type Portfolio, positions b","IMPORT com.gemstone.gemfire.cache.\"query\".data.Portfolio");
//TASK ICM3 Region 'IMPORT' not found:....[BUG : Verified Fixed ]
try{
// Index i4=(Index)qs.createIndex("boolFunctionIndex",
// IndexType.FUNCTIONAL,"boolFunction(pf.status)","/portfolios pf,
// pf.positions.values b");
//TASK ICM5 com.gemstone.gemfire.cache.query.IndexInvalidException
Object indices[]={i3}; //remove any commented Index from Array
for(int j=0;j<indices.length;j++){
CacheUtils.log(((IndexProtocol)indices[j]).isValid());
boolean r = ((IndexProtocol)indices[j]).isValid();
if(r==true){
CacheUtils.log(((IndexProtocol)indices[j]).getName());
CacheUtils.log("Test: testIndexCreation PASS");
} else{
fail("Test: testIndexCreation FAILED");
}
}
} catch(Exception e){
e.printStackTrace();
fail();
}
}
@Test
public void testComparisonBetnWithAndWithoutIndexCreationComparableObject() throws Exception {
// Task ID IUM10
SelectResults r[][]= new SelectResults[4][2];
QueryService qs;
qs = CacheUtils.getQueryService();
String queries[] = {
"select distinct * from /portfolios pf where pf.getCW(pf.ID) = $1",
"select distinct * from /portfolios pf where pf.getCW(pf.ID) > $1",
"select distinct * from /portfolios pf where pf.getCW(pf.ID) < $1",
"select distinct * from /portfolios pf where pf.getCW(pf.ID) != $1"
// TASK IUM 10
};
for (int i = 0; i < queries.length; i++) {
Query q = null;
try {
q = CacheUtils.getQueryService().newQuery(queries[i]);
Object params[] = new Object[1];
params[0] = new ComparableWrapper(1);
QueryObserverImpl observer = new QueryObserverImpl();
QueryObserverHolder.setInstance(observer);
r[i][0] = (SelectResults)q.execute(params);
if(!observer.isIndexesUsed){
CacheUtils.log("NO INDEX USED");
}
CacheUtils.log(Utils.printResult(r[i][0]));
resType1 =(r[i][0]).getCollectionType().getElementType();
resSize1 =((r[i][0]).size());
CacheUtils.log("Result Type= "+resType1);
CacheUtils.log("Result Size= "+resSize1);
set1=((r[i][0]).asSet());
// Iterator iter=set1.iterator();
} catch (Exception e) {
e.printStackTrace();
fail(q.getQueryString());
}
}
// Create an Index on status and execute the same query again.
qs = CacheUtils.getQueryService();
qs.createIndex("cIndex", IndexType.FUNCTIONAL,"pf.getCW(pf.ID)","/portfolios pf");
for (int i = 0; i < queries.length; i++) {
Query q = null;
try {
q = CacheUtils.getQueryService().newQuery(queries[i]);
Object params[] = new Object[1];
params[0] = new ComparableWrapper(1);
QueryObserverImpl observer2 = new QueryObserverImpl();
QueryObserverHolder.setInstance(observer2);
r[i][1] = (SelectResults)q.execute(params);
if(observer2.isIndexesUsed){
CacheUtils.log("YES INDEX IS USED!");
} else {
fail("FAILED: Index NOT Used");
}
CacheUtils.log(Utils.printResult(r[i][1]));
resType2 =(r[i][1]).getCollectionType().getElementType();
resSize2 =((r[i][1]).size());
set2=((r[i][1]).asSet());
} catch (Exception e) {
e.printStackTrace();
fail(q.getQueryString());
}
}
/*for(int j = 0; j <= 3 ; j++){
if ((((SelectResults)r[j][0]).getCollectionType().getElementType()).equals(((SelectResults)r[j][1]).getCollectionType().getElementType())){
CacheUtils.log("Both Search Results are of the same Type i.e.--> "+((SelectResults)r[j][0]).getCollectionType().getElementType());
}else {
fail("FAILED:Search result Type is different in both the cases");
}
if (((SelectResults)r[j][0]).size()==((SelectResults)r[j][1]).size() || ((SelectResults)r[j][1]).size()!= 0 ){
CacheUtils.log("Both Search Results are non-zero and are of Same Size i.e. Size= "+((SelectResults)r[j][1]).size());
}else {
fail("FAILED:Search result Type is different in both the cases");
}
set2=(((SelectResults)r[j][1]).asSet());
set1=(((SelectResults)r[j][0]).asSet());
if (!set1.equals(set2)){
fail();
}
}*/
CacheUtils.compareResultsOfWithAndWithoutIndex(r, this);
}
@Test
public void testIndexCreationWithIndexOperatorUsage() throws Exception {
// Task ID : ICM 18
QueryService qs;
qs = CacheUtils.getQueryService();
String[] queries = { "select distinct * from /portfolios pf where pf.collectionHolderMap[(pf.ID).toString()].arr[pf.ID] != -1" };
Object r[][] = new Object[queries.length][2];
for (int i = 0; i < queries.length; i++) {
Query q = null;
try {
q = qs.newQuery(queries[i]);
CacheUtils.getLogger().info("Executing query: " + queries[i]);
r[i][0] = q.execute();
CacheUtils.log("Executed query:" + queries[i]);
} catch (Exception e) {
e.printStackTrace();
fail(q.getQueryString());
}
}
Index i1 = qs.createIndex("fIndex", IndexType.FUNCTIONAL, "sIter",
"/portfolios pf, pf.collectionHolderMap[(pf.ID).toString()].arr sIter");
Index i2 = qs.createIndex("cIndex", IndexType.FUNCTIONAL,
"pf.collectionHolderMap[(pf.ID).toString()].arr[pf.ID]",
"/portfolios pf");
// BUG # 32498
// Index i3 = qs.createIndex("nIndex", IndexType.FUNCTIONAL,
// "pf.collectionHolderMap[((pf.ID%2)).toString()].arr[pf.ID]","/portfolios
// pf");
for (int i = 0; i < queries.length; i++) {
Query q = null;
try {
q = qs.newQuery(queries[i]);
CacheUtils.getLogger().info("Executing query: " + queries[i]);
QueryObserverImpl observer = new QueryObserverImpl();
QueryObserverHolder.setInstance(observer);
r[i][1] = q.execute();
SelectResults results = (SelectResults) r[i][1];
assertTrue(results.size() > 0);
CacheUtils.log("Executing query: " + queries[i]
+ " with index created");
if (!observer.isIndexesUsed) {
fail("Index is NOT uesd");
}
Iterator itr = observer.indexesUsed.iterator();
assertTrue(itr.hasNext());
String temp = itr.next().toString();
assertEquals(temp, "cIndex");
} catch (Exception e) {
e.printStackTrace();
fail(q.getQueryString());
}
}
CacheUtils.log(((RangeIndex) i1).dump());
CacheUtils.log(((CompactRangeIndex) i2).dump());
StructSetOrResultsSet ssOrrs = new StructSetOrResultsSet();
ssOrrs.CompareQueryResultsWithoutAndWithIndexes(r,queries.length,queries);
// CacheUtils.log(((RangeIndex)i3).dump());
// Index i3 =
// qs.createIndex("Task6Index",IndexType.FUNCTIONAL,"pos.secId","/portfolios
// pf, pf.positions.values pos");
}
@Test
public void testIndexCreationOnKeys() throws Exception {
// Task ID : ICM 9
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index i1 = qs.createIndex("kIndex", IndexType.FUNCTIONAL, "pf","/portfolios.keys pf");
Index i2 = qs.createIndex("k1Index", IndexType.FUNCTIONAL, "key","/portfolios.entries");
Index i3 = qs.createIndex("k2Index", IndexType.FUNCTIONAL, "pf","/portfolios.keys.toArray pf");
//Index i4 = qs.createIndex("k3Index", IndexType.FUNCTIONAL,
// "pf","/portfolios.keys().toArray() pf");
Index i5 = qs.createIndex("k4Index", IndexType.FUNCTIONAL, "pf","/portfolios.getKeys.asList pf");
// Index i5 = qs.createIndex("k5Index", IndexType.FUNCTIONAL,
// "pf","/portfolios.getKeys.asList() pf");
Index i6 = qs.createIndex("k5Index", IndexType.FUNCTIONAL, "pf","/portfolios.getKeys.asSet() pf");
//Index i5 = qs.createIndex("k5Index", IndexType.FUNCTIONAL,
// "pf","/portfolios.getKeys.asSet pf");
CacheUtils.log(((CompactRangeIndex)i1).dump());
CacheUtils.log(((CompactRangeIndex)i2).dump());
CacheUtils.log(((CompactRangeIndex)i3).dump());
CacheUtils.log(((CompactRangeIndex)i5).dump());
CacheUtils.log(((CompactRangeIndex)i6).dump());
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void testIndexCreationOnRegionEntry() throws Exception {
// Task ID : ICM11
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index i1 = qs.createIndex("r1Index", IndexType.FUNCTIONAL, "secId","/portfolios.values['1'].positions.values");
qs.createIndex("r12Index", IndexType.FUNCTIONAL, "secId","/portfolios['1'].positions.values");
CacheUtils.log(((CompactRangeIndex)i1).dump());
//CacheUtils.log(((RangeIndex)i2).dump());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
/**
* Creation of index on a path derived from Region.Entry object obtained
* via entrySet , fails as that function was not supported in the
* QRegion & DummyQRegion
* @author Asif
*/
@Test
public void testBug36823() {
QueryService qs;
qs = CacheUtils.getQueryService();
try{
qs.createIndex("entryIndex", IndexType.FUNCTIONAL, "value.getID()","/portfolios.entrySet pf");
Region rgn = CacheUtils.getRegion("/portfolios");
rgn.put("4",new Portfolio(4));
rgn.put("5",new Portfolio(5));
Query qr = qs.newQuery("Select distinct * from /portfolios.entrySet pf where pf.value.getID() = 4");
SelectResults sr = (SelectResults)qr.execute();
assertEquals(sr.size(),1);
}catch(Exception e) {
CacheUtils.getLogger().error(e);
fail("Test failed because of exception. e="+e);
}
}
/**
* Creation of index on key path derived from Region.Entry object obtained
* via keySet , fails as that function was not supported in the
* QRegion & DummyQRegion
* @author Asif
*/
@Test
public void testBug36590() {
QueryService qs;
qs = CacheUtils.getQueryService();
try{
qs.createIndex("keyIndex", IndexType.FUNCTIONAL, "keys","/portfolios.keySet keys");
Region rgn = CacheUtils.getRegion("/portfolios");
rgn.put("4",new Portfolio(4));
rgn.put("5",new Portfolio(5));
Query qr = qs.newQuery("Select distinct * from /portfolios.keySet keys where keys = '4'");
SelectResults sr = (SelectResults)qr.execute();
assertEquals(sr.size(),1);
}catch(Exception e) {
CacheUtils.getLogger().error(e);
fail("Test failed because of exception. e="+e);
}
}
/**
* The Index maiantenance has a bug as it does not re-evaluate the
* index maintenance collection in the IMQEvaluator when an entry
* gets modified & so the index resultset is messed up
* @author Asif
*/
@Test
public void testBug36591() {
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index i1 = qs.createIndex("keyIndex", IndexType.FUNCTIONAL, "ks.hashCode","/portfolios.keys ks");
Region rgn = CacheUtils.getRegion("/portfolios");
rgn.put("4",new Portfolio(4));
rgn.put("5",new Portfolio(5));
CacheUtils.log(((CompactRangeIndex)i1).dump());
Query qr = qs.newQuery("Select distinct * from /portfolios.keys keys where keys.hashCode >= $1");
SelectResults sr = (SelectResults)qr.execute(new Object[]{new Integer(-1)});
assertEquals(6,sr.size());
}catch(Exception e) {
CacheUtils.getLogger().error(e);
fail("Test failed because of exception. e="+e);
}
}
/**
* Creation of index on a path derived from Region.Entry object obtained
* via entrySet , fails as that function was not supported in the
* QRegion & DummyQRegion
* @author Asif
*/
@Test
public void testBug43519() {
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index index = qs.createIndex("shortIndex", IndexType.FUNCTIONAL, "p.shortID","/portfolios p");
Region rgn = CacheUtils.getRegion("/portfolios");
for (int i=1; i <= 10; i++) {
String key ="" + i;
Portfolio p = new Portfolio(i);
p.shortID = new Short(key);
// addToIndex
rgn.put(key, p);
// updateIndex
rgn.put(key, p);
if (i %2 == 0) {
// destroy from index.
rgn.destroy(key);
}
}
Query qr = qs.newQuery("Select p.shortID from /portfolios p where p.shortID < 5");
SelectResults sr = (SelectResults)qr.execute();
assertEquals(sr.size(),2);
}catch(Exception e) {
CacheUtils.getLogger().error(e);
fail("Test failed because of exception. e="+e);
}
}
/**
* Test the Index maiantenance as it may use the method keys() of QRegion
* instead of DummyQRegion while running an IndexMaintenanceQuery
* @author Asif
*/
@Test
public void testIMQFailureAsMethodKeysNAInDummyQRegion() {
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index i1 = qs.createIndex("keyIndex", IndexType.FUNCTIONAL, "ks.hashCode","/portfolios.keys() ks");
Region rgn = CacheUtils.getRegion("/portfolios");
rgn.put("4",new Portfolio(4));
rgn.put("5",new Portfolio(5));
CacheUtils.log(((CompactRangeIndex)i1).dump());
Query qr = qs.newQuery("Select distinct keys.hashCode from /portfolios.keys() keys where keys.hashCode >= $1");
SelectResults sr = (SelectResults)qr.execute(new Object[]{new Integer(-1)});
assertEquals(6,sr.size());
}catch(Exception e) {
CacheUtils.getLogger().error(e);
fail("Test failed because of exception. e="+e);
}
}
@Test
public void testIndexCreationWithFunctions() throws Exception {
// Task ID : ICM14
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index i1 = qs.createIndex("SetSecIDIndex1", IndexType.FUNCTIONAL,"b.secId","/portfolios.asSet pf, pf.positions.values b");
Index i2 = qs.createIndex("ListSecIDIndex2", IndexType.FUNCTIONAL,"b.secId","/portfolios.asList pf, pf.positions.values b");
Index i3 = qs.createIndex("ArraySecIDIndex3", IndexType.FUNCTIONAL,"b.secId","/portfolios.toArray pf, pf.positions.values b");
CacheUtils.log(((RangeIndex)i1).dump());
CacheUtils.log(((RangeIndex)i2).dump());
CacheUtils.log(((RangeIndex)i3).dump());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testInvalidIndexes() {
//Task ID: ICM15
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index i1 = qs.createIndex("r1Index", IndexType.FUNCTIONAL, "secId","/portfolios.toArray[1].positions.values");
CacheUtils.log(((RangeIndex)i1).dump());
fail("Index creation should have failed");
} catch (Exception e) {
//e.printStackTrace();
Assert.assertTrue(true);
}
try{
Index i2 = qs.createIndex("r12Index", IndexType.FUNCTIONAL, "secId","/portfolios.asList[1].positions.values");
CacheUtils.log(((RangeIndex)i2).dump());
fail("Index creation should have failed");
} catch (Exception e) {
//e.printStackTrace();
Assert.assertTrue(true);
}
}
@Test
public void testIndexCreationWithFunctionsinFromClause() throws Exception {
// Task ID: ICM13
QueryService qs;
qs = CacheUtils.getQueryService();
try{
// BUG #32586 : FIXED
Index i1 = qs.createIndex("Index11", IndexType.FUNCTIONAL,"status","/portfolios.values.toArray()");
Index i2 = qs.createIndex("Index12", IndexType.FUNCTIONAL,"ID","/portfolios.values.asSet");
Index i3 = qs.createIndex("Index13", IndexType.FUNCTIONAL,"ID","/portfolios.values.asList");
qs.createIndex("Index14", IndexType.FUNCTIONAL,"value.ID","/portfolios.entries.toArray()");
qs.createIndex("Index15", IndexType.FUNCTIONAL,"value.ID","/portfolios.entries.asSet");
qs.createIndex("Index16", IndexType.FUNCTIONAL,"value.ID","/portfolios.entries.asList");
// BUG #32586 : FIXED
qs.createIndex("Index17", IndexType.FUNCTIONAL,"kIter","/portfolios.keys.toArray() kIter");
qs.createIndex("Index18", IndexType.FUNCTIONAL,"kIter","/portfolios.keys.asSet kIter");
qs.createIndex("Index19", IndexType.FUNCTIONAL,"kIter","/portfolios.keys.asList kIter");
CacheUtils.log(((CompactRangeIndex)i1).dump());
CacheUtils.log(((CompactRangeIndex)i2).dump());
CacheUtils.log(((CompactRangeIndex)i3).dump());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testIndexObjectTypeWithRegionConstraint() {
QueryService qs;
qs = CacheUtils.getQueryService();
try{
Index i1 = qs.createIndex("Index1", IndexType.FUNCTIONAL,"b.secId","/portfolios pf, pf.positions.values b");
ObjectType type = ((IndexProtocol)i1).getResultSetType();
String fieldNames [] = {"index_iter1","index_iter2"};
ObjectType fieldTypes [] = { new ObjectTypeImpl(Portfolio.class),new ObjectTypeImpl(Object.class) };
//ObjectType expectedType = new StructTypeImpl( fieldNames,fieldTypes);
ObjectType expectedType = new StructTypeImpl( fieldNames,fieldTypes);
if( !(type instanceof StructType && type.equals(expectedType)) ){
fail("The ObjectType obtained from index is not of the expected type. Type obtained from index="+type);
}
Index i2 = qs.createIndex("Index2", IndexType.FUNCTIONAL,"pf.ID","/portfolios.values pf");
type = ((IndexProtocol)i2).getResultSetType();
expectedType = new ObjectTypeImpl( Portfolio.class);
if( ! type.equals(expectedType) ){
fail("The ObjectType obtained from index is not of the expected type. Type obtained from index="+type);
}
Index i3 = qs.createIndex("Index3", IndexType.FUNCTIONAL,"pos.secId","/portfolios['0'].positions.values pos");
type = ((IndexProtocol)i3).getResultSetType();
expectedType = new ObjectTypeImpl( Object.class);
if( ! type.equals(expectedType) ){
fail("The ObjectType obtained from index is not of the expected type. Type obtained from index="+type);
}
Index i4 = qs.createIndex("Index4", IndexType.PRIMARY_KEY,"ID","/portfolios");
type = ((IndexProtocol)i4).getResultSetType();
expectedType = new ObjectTypeImpl( Portfolio.class);
if( ! type.equals(expectedType) ){
fail("The ObjectType obtained from index is not of the expected type. Type obtained from index="+type);
}
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testIndexOnOverflowRegion() throws Exception
{
String regionName = "portfolios_overflow";
// overflow region.
AttributesFactory attributesFactory = new AttributesFactory();
attributesFactory.setValueConstraint(Portfolio.class);
attributesFactory.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(
1, EvictionAction.OVERFLOW_TO_DISK));
Region region = CacheUtils.createRegion(regionName, attributesFactory.create(), true);
for(int i=0;i<4;i++){
region.put(new Portfolio(i), new Portfolio(i));
}
QueryService qs = CacheUtils.getQueryService();
// Currently supported with compact range-index.
Index i1 = qs.createIndex("idIndex", IndexType.FUNCTIONAL, "pf.ID", "/portfolios_overflow pf");
Index i2 = qs.createIndex("keyIdIndex", IndexType.FUNCTIONAL, "key.ID", "/portfolios_overflow.keys key");
// Not yet supported with range-index.
try {
Index i3 = qs.createIndex("idIndex2", IndexType.FUNCTIONAL, "pf.ID", "/portfolios_overflow pf, pf.positions pos");
fail("Range index not supported on overflow region.");
} catch (UnsupportedOperationException ex){
// Expected.
Assert.assertTrue(true);
}
// Execute query.
String[] queryStr = new String[] {
"Select * from /portfolios_overflow pf where pf.ID = 2",
"Select * from /portfolios_overflow.keys key where key.ID = 2",
"Select * from /portfolios_overflow pf where pf.ID > 1",
"Select * from /portfolios_overflow pf where pf.ID < 2",
};
int[] resultSize = new int[] {
1,
1,
2,
2
};
for (int i=0; i < queryStr.length; i++){
Query q = qs.newQuery(queryStr[i]);
QueryObserverImpl observer = new QueryObserverImpl();
QueryObserverHolder.setInstance(observer);
SelectResults results = (SelectResults)q.execute();
if(!observer.isIndexesUsed){
fail("Index not used for query. " + queryStr[i]);
}
assertEquals(results.size(), resultSize[i]);
}
for(int i=0;i<10;i++){
region.put(new Portfolio(i), new Portfolio(i));
}
// Persistent overflow region.
}
@Test
public void testMapKeyIndexCreation_1_NonCompactType() throws Exception
{
QueryService qs;
qs = CacheUtils.getQueryService();
Index i1 = qs.createIndex("Index1", IndexType.FUNCTIONAL, "pf.positions[*]",
"/portfolios pf");
assertEquals(i1.getCanonicalizedIndexedExpression(),"index_iter1.positions[*]");
assertTrue(i1 instanceof CompactMapRangeIndex);
}
@Test
public void testMapKeyIndexCreation_2_NonCompactType() throws Exception
{
QueryService qs;
qs = CacheUtils.getQueryService();
Index i1 = qs.createIndex("Index1", IndexType.FUNCTIONAL,
"pf.positions['key1','key2','key3']", "/portfolios pf");
assertEquals(i1.getCanonicalizedIndexedExpression(),
"index_iter1.positions['key1','key2','key3']");
assertTrue(i1 instanceof CompactMapRangeIndex);
CompactMapRangeIndex mri = (CompactMapRangeIndex)i1;
Object mapKeys[] = mri.getMapKeysForTesting();
assertEquals(mapKeys.length,3);
Set<String> keys = new HashSet<String>();
keys.add("key1");
keys.add("key2");
keys.add("key3");
for(Object key:mapKeys) {
keys.remove(key);
}
assertTrue(keys.isEmpty());
String [] patterns = mri.getPatternsForTesting();
assertEquals(patterns.length,3);
Set<String> patternsSet = new HashSet<String>();
patternsSet.add("index_iter1.positions['key1']");
patternsSet.add("index_iter1.positions['key2']");
patternsSet.add("index_iter1.positions['key3']");
for(String ptrn:patterns) {
patternsSet.remove(ptrn);
}
assertTrue(patternsSet.isEmpty());
assertEquals(mri.getIndexedExpression(),"pf.positions['key1','key2','key3']");
}
/**
* Test for bug 46872, make sure
* we recover the index correctly if the cache.xml
* changes for a persistent region.
*/
@Test
public void testIndexCreationFromXML() throws Exception {
InternalDistributedSystem.getAnyInstance().disconnect();
File file = new File("persistData0");
file.mkdir();
{
Properties props = new Properties();
props.setProperty(DistributionConfig.NAME_NAME, "test");
int unusedPort = AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS);
props.setProperty("mcast-port", "0");
props.setProperty("cache-xml-file", IndexCreationJUnitTest.class.getResource("index-creation-with-eviction.xml").toURI().getPath());
DistributedSystem ds = DistributedSystem.connect(props);
// Create the cache which causes the cache-xml-file to be parsed
Cache cache = CacheFactory.create(ds);
QueryService qs = cache.getQueryService();
Region region = cache.getRegion("mainReportRegion");
for (int i = 0; i < 100; i++) {
Portfolio pf = new Portfolio(i);
pf.setCreateTime(i);
region.put(""+ i, pf);
}
//verify that a query on the creation time works as expected
SelectResults results = (SelectResults)qs.newQuery("<trace>SELECT * FROM /mainReportRegion.entrySet mr Where mr.value.createTime > 1L and mr.value.createTime < 3L").execute();
assertEquals("OQL index results did not match", 1, results.size());
cache.close();
ds.disconnect();
}
{
Properties props = new Properties();
props.setProperty(DistributionConfig.NAME_NAME, "test");
props.setProperty("mcast-port", "0");
//Using a different cache.xml that changes some region properties
//That will force the disk code to copy the region entries.
props.setProperty("cache-xml-file", IndexCreationJUnitTest.class.getResource("index-creation-without-eviction.xml").toURI().getPath());
DistributedSystem ds = DistributedSystem.connect(props);
Cache cache = CacheFactory.create(ds);
QueryService qs = cache.getQueryService();
Region region = cache.getRegion("mainReportRegion");
//verify that a query on the creation time works as expected
SelectResults results = (SelectResults)qs.newQuery("<trace>SELECT * FROM /mainReportRegion.entrySet mr Where mr.value.createTime > 1L and mr.value.createTime < 3L").execute();
assertEquals("OQL index results did not match", 1, results.size());
ds.disconnect();
FileUtil.delete(file);
}
}
@Test
public void testIndexCreationFromXMLForLocalScope() throws Exception {
InternalDistributedSystem.getAnyInstance().disconnect();
File file = new File("persistData0");
file.mkdir();
Properties props = new Properties();
props.setProperty(DistributionConfig.NAME_NAME, "test");
props.setProperty("mcast-port", "0");
props.setProperty("cache-xml-file", IndexCreationJUnitTest.class.getResource("index-creation-without-eviction.xml").toURI().getPath());
DistributedSystem ds = DistributedSystem.connect(props);
Cache cache = CacheFactory.create(ds);
Region localRegion = cache.getRegion("localRegion");
for (int i = 0; i < 100; i++) {
Portfolio pf = new Portfolio(i);
localRegion.put(""+ i, pf);
}
QueryService qs = cache.getQueryService();
Index ind = qs.getIndex(localRegion, "localIndex");
assertNotNull("Index localIndex should have been created ",ind);
// verify that a query on the creation time works as expected
SelectResults results = (SelectResults) qs.newQuery("<trace>SELECT * FROM " + localRegion.getFullPath() + " Where ID > 0").execute();
assertEquals("OQL index results did not match", 99, results.size());
ds.disconnect();
FileUtil.delete(file);
}
@Test
public void testIndexCreationFromXMLForDiskLocalScope() throws Exception {
InternalDistributedSystem.getAnyInstance().disconnect();
File file = new File("persistData0");
file.mkdir();
Properties props = new Properties();
props.setProperty(DistributionConfig.NAME_NAME, "test");
props.setProperty("mcast-port", "0");
props.setProperty("cache-xml-file", IndexCreationJUnitTest.class.getResource("index-creation-without-eviction.xml").toURI().getPath());
DistributedSystem ds = DistributedSystem.connect(props);
Cache cache = CacheFactory.create(ds);
Region localDiskRegion = cache.getRegion("localDiskRegion");
for (int i = 0; i < 100; i++) {
Portfolio pf = new Portfolio(i);
localDiskRegion.put(""+ i, pf);
}
QueryService qs = cache.getQueryService();
Index ind = qs.getIndex(localDiskRegion, "localDiskIndex");
assertNotNull("Index localIndex should have been created ",ind);
// verify that a query on the creation time works as expected
SelectResults results = (SelectResults) qs.newQuery("<trace>SELECT * FROM " + localDiskRegion.getFullPath() + " Where status = 'active'").execute();
assertEquals("OQL index results did not match", 50, results.size());
ds.disconnect();
FileUtil.delete(file);
}
@Test
public void testIndexInitializationForOverFlowRegions() throws Exception {
InternalDistributedSystem.getAnyInstance().disconnect();
File file = new File("persistData0");
file.mkdir();
{
Properties props = new Properties();
props.setProperty(DistributionConfig.NAME_NAME, "test");
int unusedPort = AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS);
props.setProperty("mcast-port", "0");
props.setProperty("statistic-sampling-enabled", "true");
props.setProperty("enable-time-statistics", "true");
props.setProperty("cache-xml-file", IndexCreationJUnitTest.class.getResource("index-recovery-overflow.xml").toURI().getPath());
DistributedSystem ds = DistributedSystem.connect(props);
// Create the cache which causes the cache-xml-file to be parsed
Cache cache = CacheFactory.create(ds);
QueryService qs = cache.getQueryService();
Region region = cache.getRegion("mainReportRegion");
for (int i = 0; i < 100; i++) {
Portfolio pf = new Portfolio(i);
pf.setCreateTime(i);
region.put(""+ i, pf);
}
IndexStatistics is1 = qs.getIndex(region, "status").getStatistics();
assertEquals(2, is1.getNumberOfKeys());
assertEquals(100, is1.getNumberOfValues());
IndexStatistics is2 = qs.getIndex(region, "ID").getStatistics();
assertEquals(100, is2.getNumberOfKeys());
assertEquals(100, is2.getNumberOfValues());
//verify that a query on the creation time works as expected
SelectResults results = (SelectResults)qs.newQuery("<trace>SELECT * FROM /mainReportRegion.entrySet mr Where mr.value.createTime > 1L and mr.value.createTime < 3L").execute();
assertEquals("OQL index results did not match", 1, results.size());
cache.close();
ds.disconnect();
}
{
Properties props = new Properties();
props.setProperty(DistributionConfig.NAME_NAME, "test");
props.setProperty("mcast-port", "0");
props.setProperty("statistic-sampling-enabled", "true");
props.setProperty("enable-time-statistics", "true");
props.setProperty("cache-xml-file", IndexCreationJUnitTest.class.getResource("index-recovery-overflow.xml").toURI().getPath());
DistributedSystem ds = DistributedSystem.connect(props);
Cache cache = CacheFactory.create(ds);
QueryService qs = cache.getQueryService();
Region region = cache.getRegion("mainReportRegion");
assertTrue("Index initialization time should not be 0.", ((LocalRegion)region).getCachePerfStats().getIndexInitializationTime() > 0);
IndexStatistics is1 = qs.getIndex(region, "status").getStatistics();
assertEquals(2, is1.getNumberOfKeys());
assertEquals(100, is1.getNumberOfValues());
IndexStatistics is2 = qs.getIndex(region, "ID").getStatistics();
assertEquals(100, is2.getNumberOfKeys());
assertEquals(100, is2.getNumberOfValues());
//verify that a query on the creation time works as expected
SelectResults results = (SelectResults)qs.newQuery("<trace>SELECT * FROM /mainReportRegion.entrySet mr Where mr.value.createTime > 1L and mr.value.createTime < 3L").execute();
assertEquals("OQL index results did not match", 1, results.size());
ds.disconnect();
FileUtil.delete(file);
}
}
@Test
public void testIndexCreationWithoutLoadingData() throws Exception {
QueryService qs;
qs = CacheUtils.getQueryService();
Index i1 = ((DefaultQueryService)qs).createIndex("statusIndex", IndexType.FUNCTIONAL,"status","/portfolios", null, false);
Index i2 = ((DefaultQueryService)qs).createIndex("secIndex", IndexType.FUNCTIONAL,"pos.secId","/portfolios p, p.positions.values pos", null, false);
Index i3 = ((DefaultQueryService)qs).createIndex("statusHashIndex", IndexType.HASH,"status","/portfolios", null, false);
assertEquals("Index should have been empty ", 0, i1.getStatistics().getNumberOfKeys());
assertEquals("Index should have been empty ", 0, i1.getStatistics().getNumberOfValues());
assertEquals("Index should have been empty ", 0, i2.getStatistics().getNumberOfKeys());
assertEquals("Index should have been empty ", 0, i2.getStatistics().getNumberOfValues());
assertEquals("Index should have been empty ", 0, i3.getStatistics().getNumberOfKeys());
assertEquals("Index should have been empty ", 0, i3.getStatistics().getNumberOfValues());
qs.removeIndexes();
i1 = ((DefaultQueryService)qs).createIndex("statusIndex", IndexType.FUNCTIONAL,"status","/portfolios", null, true);
i2 = ((DefaultQueryService)qs).createIndex("secIndex", IndexType.FUNCTIONAL,"pos.secId","/portfolios p, p.positions.values pos", null, true);
i3 = ((DefaultQueryService)qs).createIndex("statusHashIndex", IndexType.HASH,"status","/portfolios", null, true);
assertEquals("Index should not have been empty ", 2, i1.getStatistics().getNumberOfKeys());
assertEquals("Index should not have been empty ", 4, i1.getStatistics().getNumberOfValues());
assertEquals("Index should not have been empty ", 8, i2.getStatistics().getNumberOfKeys());
assertEquals("Index should not have been empty ", 8, i2.getStatistics().getNumberOfValues());
assertEquals("Index should not have been empty ", 0, i3.getStatistics().getNumberOfKeys()); // hash index does not have keys
assertEquals("Index should not have been empty ", 4, i3.getStatistics().getNumberOfValues());
}
class QueryObserverImpl extends QueryObserverAdapter{
boolean isIndexesUsed = false;
ArrayList indexesUsed = new ArrayList();
public void beforeIndexLookup(Index index, int oper, Object key) {
indexesUsed.add(index.getName());
}
public void afterIndexLookup(Collection results) {
if(results != null){
isIndexesUsed = true;
}
}
}
}