You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2015/07/09 19:02:58 UTC
[40/57] [partial] incubator-geode git commit: Initial import of
geode-1.0.0.0-SNAPSHOT-2. All the new sub-project directories (like jvsd)
were not imported. A diff was done to confirm that this commit is exactly the
same as the open directory the snapsho
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java
new file mode 100644
index 0000000..9b08b05
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java
@@ -0,0 +1,50 @@
+/*=========================================================================
+ * Copyright (c) 2002-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
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+
+package com.gemstone.gemfire.cache.lucene;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.analysis.Analyzer;
+
+
+/**
+ * An lucene index is built over the data stored in a GemFire Region.
+ * <p>
+ * An index is specified using a index name, field names, region name.
+ * <p>
+ * The index name and region name together uniquely identifies the lucene index.
+ * <p>
+ *
+ * @author Xiaojian Zhou
+ * @since 8.5
+ */
+public interface LuceneIndex {
+
+ /**
+ * @return the index name of this index
+ */
+ public String getName();
+
+ /**
+ * @return the region name for this index
+ */
+ public String getRegionName();
+
+ /**
+ * @return the indexed field names in a Set
+ */
+ public String[] getFieldNames();
+
+ /**
+ * @return the field to analyzer map
+ */
+ public Map<String, Analyzer> getFieldAnalyzerMap();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQuery.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQuery.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQuery.java
new file mode 100644
index 0000000..0579eef
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQuery.java
@@ -0,0 +1,37 @@
+package com.gemstone.gemfire.cache.lucene;
+
+import java.util.Set;
+import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory.ResultType;
+
+/**
+ * Provides wrapper object of Lucene's Query object and execute the search.
+ * <p>Instances of this interface are created using
+ * {@link LuceneQueryFactory#create}.
+ *
+ */
+public interface LuceneQuery {
+ /**
+ * Execute the search and get results.
+ */
+ public LuceneQueryResults<?> search();
+
+ /**
+ * Get page size setting of current query.
+ */
+ public int getPageSize();
+
+ /**
+ * Get limit size setting of current query.
+ */
+ public int getLimit();
+
+ /**
+ * Get result types setting of current query.
+ */
+ public ResultType[] getResultTypes();
+
+ /**
+ * Get projected fields setting of current query.
+ */
+ public String[] getProjectedFieldNames();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryFactory.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryFactory.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryFactory.java
new file mode 100644
index 0000000..5636ea4
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryFactory.java
@@ -0,0 +1,121 @@
+package com.gemstone.gemfire.cache.lucene;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.search.Query;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.DiskStore;
+
+/**
+ * Factory for creating instances of {@link LuceneQuery}.
+ * To get an instance of this factory call {@link LuceneService#createLuceneQueryFactory}.
+ * <P>
+ * To use this factory configure it with the <code>set</code> methods and then
+ * call {@link #create} to produce a {@link LuceneQuery} instance.
+ *
+ * @author Xiaojian Zhou
+ * @since 8.5
+ */
+public interface LuceneQueryFactory {
+
+ /**
+ * Default query result limit is 100
+ */
+ public static final int DEFAULT_LIMIT = 100;
+
+ /**
+ * Default page size of result is 0, which means no pagination
+ */
+ public static final int DEFAULT_PAGESIZE = 0;
+
+ public enum ResultType {
+ /**
+ * Query results only contain value, which is the default setting.
+ * If field projection is specified, use projected fields' values instead of whole domain object
+ */
+ VALUE,
+
+ /**
+ * Query results contain score
+ */
+ SCORE,
+
+ /**
+ * Query results contain key
+ */
+ KEY
+ };
+
+ /**
+ * Set page size for a query result. The default page size is 0 which means no pagination.
+ * If specified negative value, throw IllegalArgumentException
+ * @param pageSize
+ * @return itself
+ */
+ LuceneQueryFactory setPageSize(int pageSize);
+
+ /**
+ * Set max limit of result for a query
+ * If specified limit is less or equal to zero, throw IllegalArgumentException
+ * @param limit
+ * @return itself
+ */
+ LuceneQueryFactory setResultLimit(int limit);
+
+ /**
+ * set weather to include SCORE, KEY in result
+ *
+ * @param resultTypes
+ * @return itself
+ */
+ LuceneQueryFactory setResultTypes(ResultType... resultTypes);
+
+ /**
+ * Set a list of fields for result projection.
+ *
+ * @param fieldNames
+ * @return itself
+ */
+ LuceneQueryFactory setProjectionFields(String... fieldNames);
+
+ /**
+ * Create wrapper object for lucene's QueryParser object.
+ * The queryString is using lucene QueryParser's syntax. QueryParser is for easy-to-use
+ * with human understandable syntax.
+ *
+ * @param regionName region name
+ * @param indexName index name
+ * @param queryString query string in lucene QueryParser's syntax
+ * @param analyzer lucene Analyzer to parse the queryString
+ * @return LuceneQuery object
+ * @throws ParseException
+ */
+ public LuceneQuery create(String indexName, String regionName, String queryString,
+ Analyzer analyzer) throws ParseException;
+
+ /**
+ * Create wrapper object for lucene's QueryParser object using default standard analyzer.
+ * The queryString is using lucene QueryParser's syntax. QueryParser is for easy-to-use
+ * with human understandable syntax.
+ *
+ * @param regionName region name
+ * @param indexName index name
+ * @param queryString query string in lucene QueryParser's syntax
+ * @return LuceneQuery object
+ * @throws ParseException
+ */
+ public LuceneQuery create(String indexName, String regionName, String queryString)
+ throws ParseException;
+
+ /**
+ * Create wrapper object for lucene's Query object.
+ * Advanced lucene users can customized their own Query object and directly use in this API.
+ *
+ * @param regionName region name
+ * @param indexName index name
+ * @param query lucene Query object
+ * @return LuceneQuery object
+ */
+ public LuceneQuery create(String indexName, String regionName, Query query);
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java
new file mode 100644
index 0000000..d660a4b
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneQueryResults.java
@@ -0,0 +1,29 @@
+package com.gemstone.gemfire.cache.lucene;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.gemstone.gemfire.cache.execute.ResultSender;
+import com.gemstone.gemfire.distributed.DistributedMember;
+
+/**
+ * <p>
+ * Defines the interface for a container of lucene query result collected from function
+ * execution.<br>
+ *
+ * @author Xiaojian Zhou
+ * @since 8.5
+ */
+
+public interface LuceneQueryResults<E> {
+
+ /* get next page of result if pagesize is specified in query, otherwise, return null */
+ public List<E> getNextPage();
+
+ /* Is next page of result available */
+ public boolean hasNextPage();
+
+ /* total number of items */
+ public int size();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneResultStruct.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneResultStruct.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneResultStruct.java
new file mode 100644
index 0000000..a5b16b7
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneResultStruct.java
@@ -0,0 +1,59 @@
+package com.gemstone.gemfire.cache.lucene;
+
+import java.util.LinkedList;
+
+/**
+ * <p>
+ * Abstract data structure for one item in query result.
+ *
+ * @author Xiaojian Zhou
+ * @since 8.5
+ */
+public interface LuceneResultStruct {
+ /**
+ * Return the value associated with the given field name
+ *
+ * @param fieldName the String name of the field
+ * @return the value associated with the specified field
+ * @throws IllegalArgumentException If this struct does not have a field named fieldName
+ */
+ public Object getProjectedField(String fieldName);
+
+ /**
+ * Return key of the entry
+ *
+ * @return key
+ * @throws IllegalArgumentException If this struct does not contain key
+ */
+ public Object getKey();
+
+ /**
+ * Return value of the entry
+ *
+ * @return value the whole domain object
+ * @throws IllegalArgumentException If this struct does not contain value
+ */
+ public Object getValue();
+
+ /**
+ * Return score of the query
+ *
+ * @return score
+ * @throws IllegalArgumentException If this struct does not contain score
+ */
+ public Double getScore();
+
+ /**
+ * Get the types of values ordered list
+ * Item in the list could be either ResultType, or field name
+ * @return the array of result types
+ */
+ public Object[] getNames();
+
+ /**
+ * Get the values in same order as result types
+ * @return the array of values
+ */
+ public Object[] getResultValues();
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneService.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneService.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneService.java
new file mode 100644
index 0000000..dde54bf
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneService.java
@@ -0,0 +1,103 @@
+package com.gemstone.gemfire.cache.lucene;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+import com.gemstone.gemfire.cache.GemFireCache;
+
+/**
+ * LuceneService instance is a singleton for each cache. It will be created in cache
+ * constructor and get its reference via {@link GemFireCache#getLuceneService()}.
+ *
+ * It provides handle for managing the {@link LuceneIndex} and create the {@link LuceneQuery}
+ * via {@link LuceneQueryFactory}
+ *
+ * </p>
+ * Example: <br>
+ *
+ * <pre>
+ * At client and server JVM, initializing cache will create the LuceneServiceImpl object,
+ * which is a singleton at each JVM.
+ *
+ * At each server JVM, for data region to create index, create the index on fields with default analyzer:
+ * LuceneIndex index = luceneService.createIndex(indexName, regionName, "field1", "field2", "field3");
+ * or create index on fields with specified analyzer:
+ * LuceneIndex index = luceneService.createIndex(indexName, regionName, analyzerPerField);
+ *
+ * We can also create index via cache.xml or gfsh.
+ *
+ * At client side, create query and run the search:
+ *
+ * LuceneQuery query = luceneService.createLuceneQueryFactory().setLimit(200).setPageSize(20)
+ * .setResultTypes(SCORE, VALUE, KEY).setFieldProjection("field1", "field2")
+ * .create(indexName, regionName, querystring, analyzer);
+ *
+ * The querystring is using lucene's queryparser syntax, such as "field1:zhou* AND field2:gzhou@pivotal.io"
+ *
+ * LuceneQueryResults results = query.search();
+ *
+ * If pagination is not specified:
+ * List list = results.getNextPage(); // return all results in one getNextPage() call
+ * or if paging is specified:
+ * if (results.hasNextPage()) {
+ * List page = results.nextPage(); // return resules page by page
+ * }
+ *
+ * The item of the list is either the domain object or instance of {@link LuceneResultStruct}
+ * </pre>
+ *
+ * @author Xiaojian Zhou
+ *
+ */
+public interface LuceneService {
+
+ /**
+ * Create a lucene index using default analyzer.
+ *
+ * @param indexName
+ * @param regionName
+ * @param fields
+ * @return LuceneIndex object
+ */
+ public LuceneIndex createIndex(String indexName, String regionName, String... fields);
+
+ /**
+ * Create a lucene index using specified analyzer per field
+ *
+ * @param indexName index name
+ * @param regionName region name
+ * @param analyzerPerField analyzer per field map
+ * @return LuceneIndex object
+ *
+ */
+ public LuceneIndex createIndex(String indexName, String regionName,
+ Map<String, Analyzer> analyzerPerField);
+
+ /**
+ * Destroy the lucene index
+ *
+ * @param index index object
+ */
+ public void destroyIndex(LuceneIndex index);
+
+ /**
+ * Get the lucene index object specified by region name and index name
+ * @param indexName index name
+ * @param regionName region name
+ * @return LuceneIndex object
+ */
+ public LuceneIndex getIndex(String indexName, String regionName);
+
+ /**
+ * get all the lucene indexes.
+ * @return all index objects in a Collection
+ */
+ public Collection<LuceneIndex> getAllIndexes();
+
+ /**
+ * create LuceneQueryFactory
+ * @return LuceneQueryFactory object
+ */
+ public LuceneQueryFactory createLuceneQueryFactory();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceFactory.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceFactory.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceFactory.java
new file mode 100644
index 0000000..637f1c0
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceFactory.java
@@ -0,0 +1,14 @@
+package com.gemstone.gemfire.cache.lucene;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.lucene.LuceneService;
+
+public interface LuceneServiceFactory {
+
+ public void initialize();
+
+ /**
+ * Create a new LuceneService for the given cache
+ */
+ public LuceneService create(Cache cache);
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceProvider.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceProvider.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceProvider.java
new file mode 100644
index 0000000..27395ab
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneServiceProvider.java
@@ -0,0 +1,36 @@
+package com.gemstone.gemfire.cache.lucene;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.lucene.LuceneServiceFactory;
+
+public class LuceneServiceProvider {
+
+ private static final LuceneServiceFactory factory;
+
+ static {
+ ServiceLoader<LuceneServiceFactory> loader = ServiceLoader.load(LuceneServiceFactory.class);
+ Iterator<LuceneServiceFactory> itr = loader.iterator();
+ if(!itr.hasNext()) {
+ factory = null;
+ } else {
+ factory = itr.next();
+ factory.initialize();
+ }
+ }
+
+ public static LuceneService create(Cache cache) {
+
+ if(factory == null) {
+ return null;
+ }
+
+ return factory.create(cache);
+ }
+
+ private LuceneServiceProvider() {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
new file mode 100644
index 0000000..a7bdd99
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
@@ -0,0 +1,54 @@
+package com.gemstone.gemfire.cache.lucene.internal;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.analysis.Analyzer;
+
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+
+/* wrapper of IndexWriter */
+public class LuceneIndexImpl implements LuceneIndex {
+
+ /* searchable fields should belong to a specific index
+ */
+ HashSet<String> searchableFieldNames;
+
+ HashSet<String> searchablePDXFieldNames;
+
+ @Override
+ public String getName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getRegionName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String[] getFieldNames() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void initialize() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void close() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Map<String, Analyzer> getFieldAnalyzerMap() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryFactoryImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryFactoryImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryFactoryImpl.java
new file mode 100644
index 0000000..3bd5b0c
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryFactoryImpl.java
@@ -0,0 +1,88 @@
+package com.gemstone.gemfire.cache.lucene.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.queryparser.classic.ParseException;
+import org.apache.lucene.queryparser.classic.QueryParser;
+import org.apache.lucene.search.Query;
+
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.LuceneQuery;
+import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory;
+
+public class LuceneQueryFactoryImpl implements LuceneQueryFactory {
+ private int limit_attr = DEFAULT_LIMIT;
+ private int pageSize_attr = DEFAULT_PAGESIZE;
+ private Set<ResultType> resultType_attr = new HashSet<ResultType>();
+ private Set<String> projection_fields_attr = new HashSet<String>();
+
+ /* reference to the index. One index could have multiple Queries, but one Query must belong
+ * to one index
+ */
+ private LuceneIndex relatedIndex;
+
+ @Override
+ public LuceneQueryFactory setPageSize(int pageSize) {
+ this.pageSize_attr = pageSize;
+ return this;
+ }
+
+ @Override
+ public LuceneQueryFactory setResultLimit(int limit) {
+ this.limit_attr = limit;
+ return this;
+ }
+
+ @Override
+ public LuceneQueryFactory setResultTypes(ResultType... resultTypes) {
+ if (resultTypes != null) {
+ for (ResultType resultType:resultTypes) {
+ this.resultType_attr.add(resultType);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public LuceneQuery create(String indexName, String regionName,
+ String queryString, Analyzer analyzer) throws ParseException {
+ QueryParser parser = new QueryParser(null, analyzer);
+ Query query = parser.parse(queryString);
+ LuceneQueryImpl luceneQuery = new LuceneQueryImpl(indexName, regionName, limit_attr, pageSize_attr,
+ resultType_attr, projection_fields_attr, query);
+ return luceneQuery;
+ }
+
+ @Override
+ public LuceneQuery create(String indexName, String regionName,
+ String queryString) throws ParseException {
+ StandardAnalyzer analyzer = new StandardAnalyzer();
+ return create(indexName, regionName, queryString, analyzer);
+ }
+
+ @Override
+ public LuceneQuery create(String indexName, String regionName,
+ Query query) {
+ LuceneQueryImpl luceneQuery = new LuceneQueryImpl(indexName, regionName, limit_attr, pageSize_attr,
+ resultType_attr, projection_fields_attr, query);
+ return luceneQuery;
+ }
+
+ public LuceneIndex getRelatedIndex() {
+ return this.relatedIndex;
+ }
+
+ @Override
+ public LuceneQueryFactory setProjectionFields(String... fieldNames) {
+ if (fieldNames != null) {
+ for (String fieldName:fieldNames) {
+ this.projection_fields_attr.add(fieldName);
+ }
+ }
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryImpl.java
new file mode 100644
index 0000000..04025d3
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryImpl.java
@@ -0,0 +1,62 @@
+package com.gemstone.gemfire.cache.lucene.internal;
+
+import java.util.Set;
+
+import org.apache.lucene.search.Query;
+
+import com.gemstone.gemfire.cache.lucene.LuceneQuery;
+import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory;
+import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory.ResultType;
+import com.gemstone.gemfire.cache.lucene.LuceneQueryResults;
+
+public class LuceneQueryImpl implements LuceneQuery {
+ private int limit = LuceneQueryFactory.DEFAULT_LIMIT;
+ private int pageSize = LuceneQueryFactory.DEFAULT_PAGESIZE;
+ private String indexName;
+ private String regionName;
+ private Set<ResultType> resultTypes;
+
+ // The projected fields are local to a specific index per Query object.
+ private Set<String> projectedFieldNames;
+
+ /* the lucene Query object to be wrapped here */
+ private Query query;
+
+ LuceneQueryImpl(String indexName, String regionName, int limit, int pageSize, Set<ResultType> resultTypes,
+ Set<String> projectionFieldNames, Query query) {
+ this.indexName = indexName;
+ this.regionName = regionName;
+ this.limit = limit;
+ this.pageSize = pageSize;
+ this.resultTypes = resultTypes;
+ this.projectedFieldNames = projectionFieldNames;
+ this.query = query;
+ }
+
+ @Override
+ public LuceneQueryResults<?> search() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getPageSize() {
+ return this.pageSize;
+ }
+
+ @Override
+ public int getLimit() {
+ return this.limit;
+ }
+
+ @Override
+ public ResultType[] getResultTypes() {
+ return (ResultType[])this.resultTypes.toArray();
+ }
+
+ @Override
+ public String[] getProjectedFieldNames() {
+ return (String[])this.projectedFieldNames.toArray();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java
new file mode 100644
index 0000000..ecb6370
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneQueryResultsImpl.java
@@ -0,0 +1,66 @@
+package com.gemstone.gemfire.cache.lucene.internal;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.gemstone.gemfire.cache.execute.FunctionException;
+import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.cache.lucene.LuceneQueryResults;
+import com.gemstone.gemfire.cache.lucene.LuceneResultStruct;
+import com.gemstone.gemfire.distributed.DistributedMember;
+
+public class LuceneQueryResultsImpl<E> implements LuceneQueryResults<E>, ResultCollector {
+
+ @Override
+ public Object getResult() throws FunctionException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Object getResult(long timeout, TimeUnit unit)
+ throws FunctionException, InterruptedException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void addResult(DistributedMember memberID,
+ Object resultOfSingleExecution) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void endResults() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void clearResults() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public List getNextPage() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean hasNextPage() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int size() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneResultStructImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneResultStructImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneResultStructImpl.java
new file mode 100644
index 0000000..0db8f97
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneResultStructImpl.java
@@ -0,0 +1,45 @@
+package com.gemstone.gemfire.cache.lucene.internal;
+
+import java.util.LinkedList;
+
+import com.gemstone.gemfire.cache.lucene.LuceneResultStruct;
+
+public class LuceneResultStructImpl implements LuceneResultStruct {
+
+ @Override
+ public Object getProjectedField(String fieldName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Object getKey() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Object getValue() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Double getScore() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Object[] getNames() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Object[] getResultValues() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceFactoryImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceFactoryImpl.java
new file mode 100644
index 0000000..d506f7a
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceFactoryImpl.java
@@ -0,0 +1,16 @@
+package com.gemstone.gemfire.cache.lucene.internal;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.lucene.LuceneService;
+import com.gemstone.gemfire.cache.lucene.LuceneServiceFactory;
+
+public class LuceneServiceFactoryImpl implements LuceneServiceFactory {
+
+ public void initialize() {
+ }
+
+ @Override
+ public LuceneService create(Cache cache) {
+ return LuceneServiceImpl.getInstance(cache);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
new file mode 100644
index 0000000..ed90f89
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
@@ -0,0 +1,90 @@
+package com.gemstone.gemfire.cache.lucene.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.LuceneQueryFactory;
+import com.gemstone.gemfire.cache.lucene.LuceneService;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+/**
+ * Implementation of LuceneService to create lucene index and query.
+ *
+ * @author Xiaojian Zhou
+ *
+ * @since 8.5
+ */
+public class LuceneServiceImpl implements LuceneService {
+ private final Cache cache;
+ private static LuceneServiceImpl instance;
+
+ private final HashMap<String, LuceneIndex> indexMap;
+
+ private LuceneServiceImpl(final Cache cache) {
+ if (cache == null) {
+ throw new IllegalStateException(LocalizedStrings.CqService_CACHE_IS_NULL.toLocalizedString());
+ }
+ GemFireCacheImpl gfc = (GemFireCacheImpl) cache;
+ gfc.getCancelCriterion().checkCancelInProgress(null);
+
+ this.cache = gfc;
+
+
+ // Initialize the Map which maintains indexes
+ this.indexMap = new HashMap<String, LuceneIndex>();
+ }
+
+ public static synchronized LuceneServiceImpl getInstance(final Cache cache) {
+ if (instance == null) {
+ instance = new LuceneServiceImpl(cache);
+ }
+ return instance;
+ }
+
+ public String getUniqueIndexName(String indexName, String regionName) {
+ String name = indexName+"#"+regionName.replace('/', '_');
+ return name;
+ }
+
+ @Override
+ public LuceneIndex createIndex(String indexName, String regionName, String... fields) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public LuceneIndex getIndex(String indexName, String regionName) {
+ return indexMap.get(getUniqueIndexName(indexName, regionName));
+ }
+
+ @Override
+ public Collection<LuceneIndex> getAllIndexes() {
+ return indexMap.values();
+ }
+
+ @Override
+ public LuceneIndex createIndex(String indexName, String regionName,
+ Map<String, Analyzer> analyzerPerField) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void destroyIndex(LuceneIndex index) {
+ LuceneIndexImpl indexImpl = (LuceneIndexImpl)index;
+ indexMap.remove(getUniqueIndexName(index.getName(), index.getRegionName()));
+ indexImpl.close();
+ }
+
+ @Override
+ public LuceneQueryFactory createLuceneQueryFactory() {
+ return new LuceneQueryFactoryImpl();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/operations/internal/GetOperationContextImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/operations/internal/GetOperationContextImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/operations/internal/GetOperationContextImpl.java
new file mode 100644
index 0000000..b8e13c6
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/operations/internal/GetOperationContextImpl.java
@@ -0,0 +1,96 @@
+package com.gemstone.gemfire.cache.operations.internal;
+
+import com.gemstone.gemfire.cache.operations.GetOperationContext;
+import com.gemstone.gemfire.internal.offheap.Releasable;
+import com.gemstone.gemfire.internal.offheap.SimpleMemoryAllocatorImpl.Chunk;
+import com.gemstone.gemfire.internal.offheap.StoredObject;
+import com.gemstone.gemfire.internal.offheap.annotations.Unretained;
+
+/**
+ * This subclass's job is to keep customers from getting a reference to a value
+ * that is off-heap. Any access to an off-heap value should appear to the customer
+ * as a serialized value.
+ *
+ * @author dschneider
+ *
+ */
+public class GetOperationContextImpl extends GetOperationContext implements Releasable {
+
+ private boolean released;
+
+ public GetOperationContextImpl(Object key, boolean postOperation) {
+ super(key, postOperation);
+ }
+
+ /**
+ * This method is for internal use and should not be on the public apis.
+ */
+ public @Unretained Object getRawValue() {
+ return super.getValue();
+ }
+
+ @Override
+ public Object getObject() {
+ Object result = super.getObject();
+ if (result instanceof StoredObject) {
+ // For off-heap object act as if they are serialized forcing them to call getSerializedValue or getValue
+ result = null;
+ }
+ return result;
+ }
+
+ @Override
+ public void setObject(Object value, boolean isObject) {
+ this.released = false;
+ super.setObject(value, isObject);
+ }
+
+ @Override
+ public void setValue(Object value, boolean isObject) {
+ this.released = false;
+ super.setValue(value, isObject);
+ }
+
+ private void checkForReleasedOffHeapValue(Object v) {
+ // Note that we only care about Chunk (instead of all StoredObject) because it is the only one using a refcount
+ if (this.released && v instanceof Chunk) {
+ throw new IllegalStateException("Attempt to access off-heap value after the OperationContext callback returned.");
+ }
+ }
+
+ @Override
+ public byte[] getSerializedValue() {
+ byte[] result = super.getSerializedValue();
+ if (result == null) {
+ Object v = this.value;
+ if (v instanceof StoredObject) {
+ checkForReleasedOffHeapValue(v);
+ result = ((StoredObject) v).getValueAsHeapByteArray();
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Object getValue() {
+ Object result = super.getValue();
+ if (result instanceof StoredObject) {
+ checkForReleasedOffHeapValue(result);
+ result = ((StoredObject) result).getValueAsHeapByteArray();
+ }
+ return result;
+ }
+
+ @Override
+ public void release() {
+ // Note that if the context's value is stored off-heap
+ // and release has been called then we do not release
+ // our value (since this context did not retain it)
+ // but we do make sure that any future attempt to access
+ // the off-heap value fails.
+ if (this.value instanceof Chunk) {
+ this.released = true;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/Aggregator.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/Aggregator.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/Aggregator.java
new file mode 100644
index 0000000..9f54eba
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/Aggregator.java
@@ -0,0 +1,30 @@
+package com.gemstone.gemfire.cache.query;
+
+/**
+ * Behavior of a user-defined aggregator. Aggregates values and returns a
+ * result. In addition to the methods in the interface, implementing classes
+ * must have a 0-arg public constructor.
+ *
+ * @author ashahid
+ *
+ */
+public interface Aggregator {
+
+ /**
+ * Accumulate the next scalar value
+ *
+ * @param value
+ */
+ public void accumulate(Object value);
+
+ /**
+ * Initialize the Aggregator
+ */
+ public void init();
+
+ /**
+ *
+ * @return Return the result scalar value
+ */
+ public Object terminate();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractCompiledValue.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractCompiledValue.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractCompiledValue.java
index db504b6..2d64a01 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractCompiledValue.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractCompiledValue.java
@@ -229,8 +229,10 @@ public abstract class AbstractCompiledValue implements CompiledValue, Filter,
List iterators = context.getCurrentIterators();
int len = iterators.size();
if (len == 1) {
- emptySet = new ResultsBag(((RuntimeIterator) iterators.get(0))
- .getElementType(), 0, context.getCachePerfStats());
+ ObjectType elementType = ((RuntimeIterator) iterators.get(0))
+ .getElementType();
+ emptySet = context.isDistinct() ? new ResultsSet(elementType) :
+ new ResultsBag(elementType, 0, context.getCachePerfStats());
}
else {
String fieldNames[] = new String[len];
@@ -240,9 +242,8 @@ public abstract class AbstractCompiledValue implements CompiledValue, Filter,
fieldNames[i] = iter.getInternalId();
fieldTypes[i] = iter.getElementType();
}
- emptySet = new StructBag(0,
- new StructTypeImpl(fieldNames, fieldTypes),
- context.getCachePerfStats());
+ emptySet = context.isDistinct() ? new StructSet(new StructTypeImpl(fieldNames, fieldTypes))
+ :new StructBag(0, new StructTypeImpl(fieldNames, fieldTypes), context.getCachePerfStats());
}
return emptySet;
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractGroupOrRangeJunction.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractGroupOrRangeJunction.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractGroupOrRangeJunction.java
index c3e7c89..f7d9289 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractGroupOrRangeJunction.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AbstractGroupOrRangeJunction.java
@@ -11,7 +11,12 @@
*/
package com.gemstone.gemfire.cache.query.internal;
-import com.gemstone.gemfire.cache.query.AmbiguousNameException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
import com.gemstone.gemfire.cache.query.FunctionDomainException;
import com.gemstone.gemfire.cache.query.NameResolutionException;
import com.gemstone.gemfire.cache.query.QueryInvocationTargetException;
@@ -25,14 +30,6 @@ import com.gemstone.gemfire.cache.query.types.ObjectType;
import com.gemstone.gemfire.internal.Assert;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
/**
* @author asif
*
@@ -388,11 +385,12 @@ public abstract class AbstractGroupOrRangeJunction extends
currentIters.toArray(rIters);
ObjectType elementType = intermediateResults.getCollectionType()
.getElementType();
- resultSet = (elementType.isStructType()) ?
- ((SelectResults)new StructBag((StructTypeImpl)elementType,
- context.getCachePerfStats())) :
- ((SelectResults)new ResultsBag(elementType,
- context.getCachePerfStats()));
+ if(elementType.isStructType()) {
+ resultSet = QueryUtils.createStructCollection(context, (StructTypeImpl)elementType) ;
+ }else {
+ resultSet = QueryUtils.createResultCollection(context, elementType) ;
+ }
+
QueryObserver observer = QueryObserverHolder.getInstance();
try {
observer.startIteration(intermediateResults, operand);
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AllGroupJunction.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AllGroupJunction.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AllGroupJunction.java
index 32f6ed5..9e6540d 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AllGroupJunction.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/AllGroupJunction.java
@@ -125,18 +125,16 @@ public class AllGroupJunction extends AbstractCompiledValue implements Filter,
if (finalList.size() > 1) {
StructType type = QueryUtils
.createStructTypeForRuntimeIterators(finalList);
- return new StructBag((StructTypeImpl)type,
- context.getCachePerfStats());
+ return QueryUtils.createStructCollection(context, type);
}
else {
ObjectType type = ((RuntimeIterator) finalList.iterator().next())
.getElementType();
if (type instanceof StructType) {
- return new StructBag((StructTypeImpl)type,
- context.getCachePerfStats());
+ return QueryUtils.createStructCollection(context, (StructTypeImpl)type);
}
else {
- return new ResultsBag(type, context.getCachePerfStats());
+ return QueryUtils.createResultCollection(context, type);
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/Bag.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/Bag.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/Bag.java
new file mode 100644
index 0000000..2f4dd87
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/Bag.java
@@ -0,0 +1,717 @@
+/*=========================================================================
+ * Copyright (c) 2005-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
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+
+package com.gemstone.gemfire.cache.query.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.AbstractCollection;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.cache.query.CqResults;
+import com.gemstone.gemfire.cache.query.SelectResults;
+import com.gemstone.gemfire.cache.query.internal.ObjectIntHashMap.Entry;
+import com.gemstone.gemfire.cache.query.internal.types.CollectionTypeImpl;
+import com.gemstone.gemfire.cache.query.types.CollectionType;
+import com.gemstone.gemfire.cache.query.types.ObjectType;
+import com.gemstone.gemfire.cache.query.types.StructType;
+import com.gemstone.gemfire.internal.DataSerializableFixedID;
+import com.gemstone.gemfire.internal.Version;
+import com.gemstone.gemfire.internal.cache.CachePerfStats;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+// @todo probably should assert element type when elements added
+// @todo support generics when no longer support Java 1.4
+/**
+ * Implementation of SelectResults that allows duplicates . The keys store the
+ * elements of the collection and the the values store the number of occurrences
+ * as an int.
+ *
+ * @see ResultsBag
+ * @see StructBag
+ * @see SortedResultsBag
+ *
+ * @author Eric Zoerner
+ * @author ashahid
+ * @since 8.1
+ */
+public abstract class Bag<E> extends AbstractCollection<E> implements
+ CqResults<E> {
+ protected ObjectType elementType;
+ // protected ObjectIntHashMap map;
+ protected int size = 0;
+
+ /** adds support for null elements */
+
+ protected int numNulls = 0;
+ // Asif: These fields are used for limiting the results based on the limit
+ // clause in the query
+ private int limit = -1;
+ boolean hasLimitIterator = false;
+ final Object limitLock = new Object();
+
+ public Bag() {
+
+ }
+
+ /**
+ * This constructor should only be used by the DataSerializer. Creates a
+ * ResultsBag with no fields.
+ */
+ public Bag(boolean ignored) {
+ }
+
+ /**
+ * @param stats
+ * the CachePerfStats to track hash collisions. Should be null unless
+ * this is used as a query execution-time result set.
+ */
+ public Bag(CachePerfStats stats) {
+
+ }
+
+ /**
+ * @param stats
+ * the CachePerfStats to track hash collisions. Should be null unless
+ * this is used as a query execution-time result set.
+ */
+ Bag(Collection c, CachePerfStats stats) {
+ this(stats);
+ for (Iterator itr = c.iterator(); itr.hasNext();) {
+ this.add(itr.next());
+ }
+ }
+
+ /**
+ * @param stats
+ * the CachePerfStats to track hash collisions. Should be null unless
+ * this is used as a query execution-time result set.
+ */
+ Bag(SelectResults sr, CachePerfStats stats) {
+ this((Collection) sr, stats);
+ // grab type info
+ setElementType(sr.getCollectionType().getElementType());
+ }
+
+ /**
+ * @param stats
+ * the CachePerfStats to track hash collisions. Should be null unless
+ * this is used as a query execution-time result set.
+ */
+ Bag(ObjectType elementType, CachePerfStats stats) {
+ this(stats);
+ setElementType(elementType);
+ }
+
+ public void setElementType(ObjectType elementType) {
+ if (elementType instanceof StructType)
+ throw new IllegalArgumentException(
+ LocalizedStrings.ResultsBag_THIS_COLLECTION_DOES_NOT_SUPPORT_STRUCT_ELEMENTS
+ .toLocalizedString());
+ this.elementType = elementType;
+ }
+
+ // @todo Currently does an iteration, could make this more efficient
+ // by providing a ListView
+ /**
+ * Returns this bag as a list.
+ */
+ public List asList() {
+ return new ArrayList(this);
+ }
+
+ /**
+ * Return an unmodifiable Set view of this bag. Does not require an iteration
+ * by using a lightweight wrapper.
+ */
+ public Set asSet() {
+ return new SetView();
+ }
+
+ public CollectionType getCollectionType() {
+ return new CollectionTypeImpl(Collection.class, this.elementType);
+ }
+
+ public abstract boolean isModifiable();
+
+ public int occurrences(Object element) {
+ if (this.hasLimitIterator) {
+ // Asif: If limit iterator then occurrence should be calculated
+ // via the limit iterator
+ int count = 0;
+ boolean encounteredObject = false;
+ for (Iterator itr = this.iterator(); itr.hasNext();) {
+ Object v = itr.next();
+ if (element == null ? v == null : element.equals(v)) {
+ count++;
+ encounteredObject = true;
+ } else if (encounteredObject) {
+ // Asif: No possibility of its occurrence again
+ break;
+ }
+ }
+ return count;
+ } else {
+ if (element == null) {
+ return this.numNulls;
+ }
+ return this.mapGet(element); // returns 0 if not
+ // found
+ }
+ }
+
+ protected abstract int mapGet(Object element);
+
+ /**
+ * Return an iterator over the elements in this collection. Duplicates will
+ * show up the number of times it has occurrences.
+ */
+ @Override
+ public Iterator iterator() {
+ if (this.hasLimitIterator) {
+ // Asif: Return a new LimitIterator in the block so that
+ // the current Limit does not get changed by a remove
+ // operation of another thread. The current limit is
+ // set in the limit iterator. So the setting of the current limit
+ // & creation of iterator should be atomic .If any subsequent
+ // modifcation in limit occurs, the iterator will itself fail.
+ // Similarly a remove called by a iterator should decrease the
+ // current limit and underlying itr.remove atomically
+ synchronized (this.limitLock) {
+ return new LimitBagIterator();
+ }
+ } else {
+ return new BagIterator();
+ }
+ }
+
+ @Override
+ public boolean contains(Object element) {
+ if (this.hasLimitIterator) {
+ return super.contains(element);
+ } else {
+ if (element == null) {
+ return this.numNulls > 0;
+ }
+ return mapContainsKey(element);
+ }
+ }
+
+ protected abstract boolean mapContainsKey(Object element);
+
+ // not thread safe!
+ @Override
+ public boolean add(Object element) {
+ if (this.limit > -1) {
+ throw new UnsupportedOperationException(
+ "Addition to the SelectResults not allowed as the query result is constrained by LIMIT");
+ }
+ if (element == null) {
+ numNulls++;
+ } else {
+ int count = this.mapGet(element); // 0 if not
+ // found
+ this.mapPut(element, count + 1);
+ }
+ this.size++;
+ assert this.size >= 0 : this.size;
+ return true;
+ }
+
+ protected abstract void mapPut(Object element, int count);
+
+ // Internal usage method
+ // Asif :In case of StructBag , we will ensure that it
+ // gets an Object [] indicating field values as parameter
+ // from the CompiledSelect
+ public int addAndGetOccurence(Object element) {
+ int occurence;
+ if (element == null) {
+ numNulls++;
+ occurence = numNulls;
+ } else {
+ occurence = this.mapGet(element); // 0 if not
+ // found
+ this.mapPut(element, ++occurence);
+ }
+ this.size++;
+ assert this.size >= 0 : this.size;
+ return occurence;
+ }
+
+ @Override
+ public int size() {
+ if (this.hasLimitIterator) {
+ synchronized (this.limitLock) {
+ return this.limit;
+ }
+ } else {
+ return this.size;
+ }
+ }
+
+ protected abstract int mapSize();
+
+ // not thread safe!
+ @Override
+ public boolean remove(Object element) {
+ if (this.hasLimitIterator) {
+ return super.remove(element);
+ } else {
+ if (element == null) {
+ if (this.numNulls > 0) {
+ this.numNulls--;
+ this.size--;
+ assert this.size >= 0 : this.size;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ int count = this.mapGet(element); // 0 if not
+ // found
+ if (count == 0) {
+ return false;
+ }
+ if (count == 1) {
+ this.mapRemove(element);
+ } else {
+ this.mapPut(element, --count);
+ }
+ this.size--;
+ assert this.size >= 0 : this.size;
+ return true;
+ }
+ }
+
+ protected abstract int mapRemove(Object element);
+
+ // not thread safe!
+ @Override
+ public void clear() {
+ this.mapClear();// this.map.clear();
+ this.numNulls = 0;
+ this.size = 0;
+ if (this.hasLimitIterator) {
+ synchronized (this.limitLock) {
+ this.limit = 0;
+ }
+ }
+ }
+
+ protected abstract void mapClear();
+
+ // not thread safe!
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Bag)) {
+ return false;
+ }
+ Bag otherBag = (Bag) o;
+ return this.size == otherBag.size
+ && this.elementType.equals(otherBag.elementType)
+
+ && this.getMap().equals(otherBag.getMap())
+ && this.numNulls == otherBag.numNulls;
+ }
+
+ protected abstract Object getMap();
+
+ @Override
+ // GemStoneAddition
+ public int hashCode() {
+ return this.mapHashCode();
+ }
+
+ protected abstract int mapHashCode();
+
+ public boolean addAll(Collection coll) {
+ if (this.limit > -1) {
+ throw new UnsupportedOperationException(
+ "Addition to the SelectResults not allowed as the query result is constrained by LIMIT");
+ } else {
+ return super.addAll(coll);
+ }
+ }
+
+ /**
+ *
+ * @param out
+ * @throws IOException
+ */
+ void writeNumNulls(DataOutput out) throws IOException {
+ out.writeInt(this.numNulls);
+ }
+
+ /**
+ *
+ * @param in
+ * @throws IOException
+ */
+ void readNumNulls(DataInput in) throws IOException {
+ this.numNulls = in.readInt();
+ }
+
+ void applyLimit(int limit) {
+ this.limit = limit;
+ // Asif : From the code of IntHashMap, it appears that if no data is
+ // going to be added , then the rehash does not occur & default code
+ // of rehash does not appear to change the order of data . So we can assume
+ // that this iterator will be returning data in order.
+ // Limit Iterator is needed if the limit happens to be less than the size
+ if (this.limit > -1 && this.size > this.limit) {
+ this.hasLimitIterator = true;
+ }
+ }
+
+ protected boolean nullOutputAtBegining() {
+ return true;
+ }
+
+ protected abstract boolean mapEmpty();
+
+ protected abstract Iterator mapEntryIterator();
+
+ protected abstract Iterator mapKeyIterator();
+
+ protected abstract Object keyFromEntry(Object entry);
+
+ protected abstract Integer valueFromEntry(Object entry);
+
+ private void checkModifiablity() {
+ if (!Bag.this.isModifiable()) {
+ throw new UnsupportedOperationException("Collection unmodifiable");
+ }
+ }
+
+ protected class BagIterator implements Iterator {
+ private final Iterator iter;
+
+ protected BagIterator() {
+ if (nullOutputAtBegining()) {
+ this.iter = new NullFirstBagIterator();
+ } else {
+ this.iter = new NullLastBagIterator();
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return this.iter.hasNext();
+ }
+
+ @Override
+ public Object next() {
+ return this.iter.next();
+ }
+
+ @Override
+ public void remove() {
+ this.iter.remove();
+ }
+
+ private class NullLastBagIterator implements Iterator {
+ final Iterator mapIterator = Bag.this.mapEntryIterator();
+
+ Object currentEntry = null;
+
+ /**
+ * duplicates are numbered from 1 to n; 0 = no current, otherwise goes
+ * from 1 to dupLimit, indicating the last dup that was emitted by next()
+ */
+ int currentDup = 0;
+ int dupLimit = 0;
+
+ int nullDup = 0;
+ int nullDupLimit = Bag.this.numNulls;
+
+ public boolean hasNext() {
+ return this.mapIterator.hasNext() || this.currentDup < this.dupLimit
+ || this.nullDup < this.nullDupLimit;
+ }
+
+ public Object next() {
+ // see if there is another duplicate to emit
+ if (this.currentDup < this.dupLimit) {
+ this.currentDup++;
+ return Bag.this.keyFromEntry(currentEntry);
+ } else if (this.mapIterator.hasNext()) {
+ // otherwise, go to next object
+ currentEntry = this.mapIterator.next();
+ this.dupLimit = Bag.this.valueFromEntry(currentEntry);
+ this.currentDup = 1;
+ return Bag.this.keyFromEntry(currentEntry);
+ } else if (this.nullDup < this.nullDupLimit) {
+ ++this.nullDup;
+ return null;
+ } else {
+ throw new NoSuchElementException();
+ }
+
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("remove not supported");
+ }
+ }
+
+ private class NullFirstBagIterator implements Iterator {
+ final Iterator mapIterator = Bag.this.mapEntryIterator();
+ Object currentEntry = null;
+
+ /**
+ * duplicates are numbered from 1 to n; 0 = no current, otherwise goes
+ * from 1 to dupLimit, indicating the last dup that was emitted by next()
+ */
+ int currentDup = 0;
+ /**
+ * dupLimit is the total number of occurrences; start by emitting the
+ * nulls
+ */
+ int dupLimit = Bag.this.numNulls;
+
+ public boolean hasNext() {
+ return this.mapIterator.hasNext() || this.currentDup < this.dupLimit;
+ }
+
+ public Object next() {
+ // see if there is another duplicate to emit
+ if (this.currentDup < this.dupLimit) {
+ this.currentDup++;
+ return (this.currentEntry == null) ? null : Bag.this
+ .keyFromEntry(currentEntry);
+ }
+ // otherwise, go to next object
+ currentEntry = this.mapIterator.next();
+ this.dupLimit = Bag.this.valueFromEntry(currentEntry); // (Integer)
+
+ this.currentDup = 1;
+ return Bag.this.keyFromEntry(currentEntry);
+ }
+
+ public void remove() {
+ checkModifiablity();
+ if (this.currentDup == 0) {
+ // next has not yet been called
+ throw new IllegalStateException(
+ LocalizedStrings.ResultsBag_NEXT_MUST_BE_CALLED_BEFORE_REMOVE
+ .toLocalizedString());
+ }
+
+ this.dupLimit--;
+ assert this.dupLimit >= 0 : this.dupLimit;
+ if (this.currentEntry == null) {
+ Bag.this.numNulls = this.dupLimit;
+ assert Bag.this.numNulls >= 0 : Bag.this.numNulls;
+ } else {
+ if (this.dupLimit > 0) {
+ Bag.this.mapPut(Bag.this.keyFromEntry(currentEntry), this.dupLimit);
+ } else {
+ this.mapIterator.remove();
+ }
+ }
+ Bag.this.size--;
+ this.currentDup--;
+ assert Bag.this.size >= 0 : Bag.this.size;
+ assert this.currentDup >= 0 : this.currentDup;
+ }
+ }
+ }
+
+ /**
+ * package visibility so ResultsCollectionWrapper can reference it. This
+ * SetView is serialized as a special case by a ResultsCollectionWrapper.
+ * Keith: Refactored to add consideration for LIMIT, April 1, 2009
+ *
+ * @see ResultsCollectionWrapper#toData
+ */
+ class SetView extends AbstractSet {
+
+ private int localLimit;
+
+ SetView() {
+ localLimit = Bag.this.limit;
+ }
+
+ public Iterator iterator() {
+ if (localLimit > -1) {
+ return new LimitSetViewIterator();
+ } else {
+ return new SetViewIterator();
+ }
+ }
+
+ @Override
+ public boolean add(Object o) {
+ if (contains(o)) {
+ return false;
+ }
+ return Bag.this.add(o);
+ }
+
+ @Override
+ public void clear() {
+ Bag.this.clear();
+ }
+
+ @Override
+ public int size() {
+ int calculatedSize = Bag.this.mapSize() + (Bag.this.numNulls > 0 ? 1 : 0);
+ if (localLimit > -1) {
+ return Math.min(localLimit, calculatedSize);
+ }
+ return calculatedSize;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ if (o == null) {
+ return Bag.this.numNulls > 0;
+ }
+ return Bag.this.mapContainsKey(o);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ if (localLimit == 0) {
+ return true;
+ }
+ if (Bag.this.numNulls > 0) {
+ return false;
+ }
+ return Bag.this.mapEmpty();
+ }
+
+ public class SetViewIterator implements Iterator {
+ /** need to emit a null value if true */
+ boolean emitNull = Bag.this.numNulls > 0;
+ final Iterator it = Bag.this.mapKeyIterator();
+ boolean currentIsNull = false;
+
+ public Object next() {
+ if (this.emitNull) {
+ this.emitNull = false;
+ currentIsNull = true;
+ return null;
+ }
+ Object key = it.next();
+ currentIsNull = false;
+ return key;
+ }
+
+ public boolean hasNext() {
+ if (this.emitNull) {
+ return true;
+ }
+ return it.hasNext();
+ }
+
+ public void remove() {
+ if (currentIsNull) {
+ Bag.this.numNulls = 0;
+ } else {
+ it.remove();
+ }
+ }
+ };
+
+ class LimitSetViewIterator extends SetViewIterator {
+ private int currPos = 0;
+ private Object currentKey;
+
+ @Override
+ public Object next() {
+ if (this.currPos == Bag.SetView.this.localLimit) {
+ throw new NoSuchElementException();
+ } else {
+ currentKey = super.next();
+ ++currPos;
+ return currentKey;
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return (this.currPos < Bag.SetView.this.localLimit) && super.hasNext();
+ }
+
+ @Override
+ public void remove() {
+ if (this.currPos == 0) {
+ // next has not yet been called
+ throw new IllegalStateException(
+ "next() must be called before remove()");
+ }
+ synchronized (Bag.this.limitLock) {
+ if (currentIsNull) {
+ Bag.this.limit -= Bag.this.numNulls;
+ Bag.this.numNulls = 0;
+ Bag.SetView.this.localLimit--;
+ } else {
+ int count = Bag.this.mapRemove(currentKey);
+ assert count != 0 : "Attempted to remove an element that was not in the map.";
+ Bag.this.limit -= count;
+ ResultsBag.SetView.this.localLimit--;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @author Asif
+ *
+ */
+ protected class LimitBagIterator extends Bag.BagIterator {
+ final private int localLimit;
+
+ private int currPos = 0;
+
+ /**
+ * guarded by ResultsBag.this.limitLock object
+ */
+ public LimitBagIterator() {
+ localLimit = Bag.this.limit;
+ }
+
+ public boolean hasNext() {
+ return this.currPos < this.localLimit;
+ }
+
+ public Object next() {
+ if (this.currPos == this.localLimit) {
+ throw new NoSuchElementException();
+ } else {
+ Object next = super.next();
+ ++currPos;
+ return next;
+ }
+
+ }
+
+ public void remove() {
+ if (this.currPos == 0) {
+ // next has not yet been called
+ throw new IllegalStateException("next() must be called before remove()");
+ }
+ synchronized (Bag.this.limitLock) {
+ super.remove();
+ --Bag.this.limit;
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledAggregateFunction.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledAggregateFunction.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledAggregateFunction.java
new file mode 100644
index 0000000..ba77310
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledAggregateFunction.java
@@ -0,0 +1,169 @@
+package com.gemstone.gemfire.cache.query.internal;
+
+import com.gemstone.gemfire.cache.query.AmbiguousNameException;
+import com.gemstone.gemfire.cache.query.FunctionDomainException;
+import com.gemstone.gemfire.cache.query.NameResolutionException;
+import com.gemstone.gemfire.cache.query.QueryInvocationTargetException;
+import com.gemstone.gemfire.cache.query.TypeMismatchException;
+import com.gemstone.gemfire.cache.query.internal.aggregate.AvgBucketNode;
+import com.gemstone.gemfire.cache.query.internal.aggregate.AvgDistinct;
+import com.gemstone.gemfire.cache.query.internal.aggregate.AvgDistinctPRQueryNode;
+import com.gemstone.gemfire.cache.query.internal.aggregate.AvgPRQueryNode;
+import com.gemstone.gemfire.cache.query.internal.aggregate.Count;
+import com.gemstone.gemfire.cache.query.internal.aggregate.CountDistinct;
+import com.gemstone.gemfire.cache.query.internal.aggregate.CountDistinctPRQueryNode;
+import com.gemstone.gemfire.cache.query.internal.aggregate.SumDistinctPRQueryNode;
+import com.gemstone.gemfire.cache.query.internal.aggregate.CountPRQueryNode;
+import com.gemstone.gemfire.cache.query.internal.aggregate.DistinctAggregator;
+import com.gemstone.gemfire.cache.query.internal.aggregate.MaxMin;
+import com.gemstone.gemfire.cache.query.internal.aggregate.Avg;
+import com.gemstone.gemfire.cache.query.internal.aggregate.Sum;
+import com.gemstone.gemfire.cache.query.internal.aggregate.SumDistinct;
+import com.gemstone.gemfire.cache.query.internal.parse.OQLLexerTokenTypes;
+import com.gemstone.gemfire.cache.query.internal.types.ObjectTypeImpl;
+import com.gemstone.gemfire.cache.query.types.ObjectType;
+
+/**
+ *
+ * @author ashahid
+ *
+ */
+public class CompiledAggregateFunction extends AbstractCompiledValue {
+
+ private final CompiledValue expr;
+ private final int aggFuncType;
+ private final boolean distinctOnly;
+
+ public CompiledAggregateFunction(CompiledValue expr, int aggFunc) {
+ this(expr, aggFunc, false);
+ }
+
+ public CompiledAggregateFunction(CompiledValue expr, int aggFunc,
+ boolean distinctOnly) {
+ this.expr = expr;
+ this.aggFuncType = aggFunc;
+ this.distinctOnly = distinctOnly;
+ }
+
+ @Override
+ public int getType() {
+
+ return AGG_FUNC;
+ }
+
+ @Override
+ public Object evaluate(ExecutionContext context)
+ throws FunctionDomainException, TypeMismatchException,
+ NameResolutionException, QueryInvocationTargetException {
+ boolean isPRQueryNode = context.getIsPRQueryNode();
+ boolean isBucketNode = context.getBucketList() != null;
+ switch (this.aggFuncType) {
+
+ case OQLLexerTokenTypes.SUM:
+ if (isPRQueryNode) {
+ return this.distinctOnly ? new SumDistinctPRQueryNode() : new Sum();
+ } else {
+ return this.distinctOnly ? (isBucketNode ? new DistinctAggregator()
+ : new SumDistinct()) : new Sum();
+ }
+
+ case OQLLexerTokenTypes.MAX:
+ return new MaxMin(true);
+
+ case OQLLexerTokenTypes.MIN:
+ return new MaxMin(false);
+
+ case OQLLexerTokenTypes.AVG:
+ if (isPRQueryNode) {
+ return this.distinctOnly ? new AvgDistinctPRQueryNode()
+ : new AvgPRQueryNode();
+ } else {
+ return this.distinctOnly ? (isBucketNode ? new DistinctAggregator()
+ : new AvgDistinct()) : (isBucketNode ? new AvgBucketNode()
+ : new Avg());
+ }
+
+ case OQLLexerTokenTypes.COUNT:
+ if (isPRQueryNode) {
+ return this.distinctOnly ? new CountDistinctPRQueryNode()
+ : new CountPRQueryNode();
+ } else {
+ return this.distinctOnly ? (isBucketNode ? new DistinctAggregator()
+ : new CountDistinct()) : new Count();
+ }
+
+ default:
+ throw new UnsupportedOperationException(
+ "Aggregate function not implemented");
+
+ }
+
+ }
+
+ private String getStringRep() {
+ switch (this.aggFuncType) {
+
+ case OQLLexerTokenTypes.SUM:
+ return "sum";
+
+ case OQLLexerTokenTypes.MAX:
+ return "max";
+
+ case OQLLexerTokenTypes.MIN:
+ return "min";
+
+ case OQLLexerTokenTypes.AVG:
+ return "avg";
+ case OQLLexerTokenTypes.COUNT:
+ return "count";
+ default:
+ throw new UnsupportedOperationException(
+ "Aggregate function not implemented");
+
+ }
+ }
+
+ public int getFunctionType() {
+ return this.aggFuncType;
+ }
+
+ public CompiledValue getParameter() {
+ return this.expr;
+ }
+
+ public ObjectType getObjectType() {
+ switch (this.aggFuncType) {
+
+ case OQLLexerTokenTypes.SUM:
+ case OQLLexerTokenTypes.MAX:
+ case OQLLexerTokenTypes.MIN:
+ case OQLLexerTokenTypes.AVG:
+ return new ObjectTypeImpl(Number.class);
+
+ case OQLLexerTokenTypes.COUNT:
+ return new ObjectTypeImpl(Integer.class);
+
+ default:
+ throw new UnsupportedOperationException(
+ "Aggregate function not implemented");
+
+ }
+ }
+
+ @Override
+ public void generateCanonicalizedExpression(StringBuffer clauseBuffer,
+ ExecutionContext context) throws AmbiguousNameException,
+ TypeMismatchException, NameResolutionException {
+ clauseBuffer.insert(0, ')');
+ if (this.expr != null) {
+ this.expr.generateCanonicalizedExpression(clauseBuffer, context);
+ } else {
+ clauseBuffer.insert(0, '*');
+ }
+ if (this.distinctOnly) {
+ clauseBuffer.insert(0, "distinct ");
+ }
+ clauseBuffer.insert(0, '(');
+ clauseBuffer.insert(0, getStringRep());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledBindArgument.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledBindArgument.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledBindArgument.java
index 4cd1989..46123bc 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledBindArgument.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledBindArgument.java
@@ -41,16 +41,19 @@ public class CompiledBindArgument extends AbstractCompiledValue {
public void generateCanonicalizedExpression(StringBuffer clauseBuffer,
ExecutionContext context) throws AmbiguousNameException,
TypeMismatchException, NameResolutionException {
- Object rgn;
- if ((rgn = context.getBindArgument(this.index)) instanceof Region) {
- clauseBuffer.insert(0, ((Region)rgn).getFullPath());
- }
- else {
- super.generateCanonicalizedExpression(clauseBuffer, context);
+
+ Object bindArg;
+ if (context.isBindArgsSet() && (bindArg = context.getBindArgument(this.index)) instanceof Region ) {
+ clauseBuffer.insert(0, ((Region) bindArg).getFullPath());
+ }else {
+ clauseBuffer.insert(0, "$" + this.index);
}
}
public Object evaluate(ExecutionContext context) {
+ if(!context.isBindArgsSet()) {
+ return null;
+ }
Object obj = context.getBindArgument(this.index);
// check for BucketRegion substitution
if (obj instanceof Region) {
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/31d1b20e/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledComparison.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledComparison.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledComparison.java
index f309a9b..d7d382d 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledComparison.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/query/internal/CompiledComparison.java
@@ -8,7 +8,9 @@
*/
package com.gemstone.gemfire.cache.query.internal;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.query.AmbiguousNameException;
@@ -18,6 +20,7 @@ import com.gemstone.gemfire.cache.query.NameResolutionException;
import com.gemstone.gemfire.cache.query.QueryInvocationTargetException;
import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.cache.query.SelectResults;
+import com.gemstone.gemfire.cache.query.Struct;
import com.gemstone.gemfire.cache.query.TypeMismatchException;
import com.gemstone.gemfire.cache.query.internal.index.IndexData;
import com.gemstone.gemfire.cache.query.internal.index.IndexProtocol;
@@ -27,6 +30,7 @@ import com.gemstone.gemfire.cache.query.internal.types.StructTypeImpl;
import com.gemstone.gemfire.cache.query.internal.types.TypeUtils;
import com.gemstone.gemfire.cache.query.types.ObjectType;
import com.gemstone.gemfire.cache.query.types.StructType;
+import com.gemstone.gemfire.internal.offheap.annotations.Retained;
import com.gemstone.gemfire.pdx.PdxInstance;
import com.gemstone.gemfire.pdx.internal.PdxString;
@@ -143,7 +147,7 @@ public class CompiledComparison extends AbstractCompiledValue implements
@Override
public SelectResults filterEvaluate(ExecutionContext context,
SelectResults intermediateResults, boolean completeExpansionNeeded,
- CompiledValue iterOperands, RuntimeIterator[] indpndntItrs, boolean isIntersection, boolean conditioningNeeded, boolean evaluateProjection)
+ @Retained CompiledValue iterOperands, RuntimeIterator[] indpndntItrs, boolean isIntersection, boolean conditioningNeeded, boolean evaluateProjection)
throws FunctionDomainException, TypeMismatchException,
NameResolutionException, QueryInvocationTargetException {
// see if we're dependent on the current iterator
@@ -324,7 +328,7 @@ public class CompiledComparison extends AbstractCompiledValue implements
// Invariant: the receiver is dependent on the current iterator.
private SelectResults singleBaseCollectionFilterEvaluate(
ExecutionContext context, SelectResults intermediateResults,
- final boolean completeExpansionNeeded, CompiledValue iterOperands,
+ final boolean completeExpansionNeeded, @Retained CompiledValue iterOperands,
IndexInfo indexInfo, RuntimeIterator[] indpndntItr, boolean isIntersection, boolean conditioningNeeded, boolean evaluateProj)
throws TypeMismatchException, AmbiguousNameException,
FunctionDomainException, NameResolutionException,
@@ -374,11 +378,13 @@ public class CompiledComparison extends AbstractCompiledValue implements
// we get the right idea. Also right now we will assume that only single
// iterator cases will be candidates for this oprtmization.
// dependent iterators will come later.
- boolean useLinkedSet = false;
+ boolean useLinkedDataStructure = false;
+ boolean nullValuesAtStart = true;
Boolean orderByClause = (Boolean)context.cacheGet(CompiledValue.CAN_APPLY_ORDER_BY_AT_INDEX);
if(orderByClause != null && orderByClause.booleanValue()) {
List orderByAttrs = (List)context.cacheGet(CompiledValue.ORDERBY_ATTRIB);
- useLinkedSet =orderByAttrs.size()==1;
+ useLinkedDataStructure =orderByAttrs.size()==1;
+ nullValuesAtStart = !((CompiledSortCriterion)orderByAttrs.get(0)).getCriterion();
}
// ////////////////////////////////////////////////////////////////
if (!conditioningNeeded) {
@@ -395,11 +401,11 @@ public class CompiledComparison extends AbstractCompiledValue implements
context.getCache().getLogger().fine(
"StructType resultType.class="
+ resultType.getClass().getName());
- if(useLinkedSet) {
- set = new LinkedStructSet((StructTypeImpl)resultType);
+ if(useLinkedDataStructure) {
+ set = context.isDistinct() ? new LinkedStructSet((StructTypeImpl)resultType)
+ : new SortedResultsBag<Struct>((StructTypeImpl)resultType, nullValuesAtStart);
}else {
- set = new StructBag((StructTypeImpl)resultType,
- context.getCachePerfStats());
+ set = QueryUtils.createStructCollection(context, (StructTypeImpl)resultType) ;
}
indexFieldsSize = ((StructTypeImpl)resultType).getFieldNames().length;
}
@@ -407,10 +413,11 @@ public class CompiledComparison extends AbstractCompiledValue implements
context.getCache().getLogger().fine(
"non-StructType resultType.class="
+ resultType.getClass().getName());
- if (useLinkedSet) {
- set = new LinkedResultSet(resultType);
+ if (useLinkedDataStructure) {
+ set = context.isDistinct() ? new LinkedResultSet(resultType) :
+ new SortedResultsBag(resultType, nullValuesAtStart) ;
} else {
- set = new ResultsBag(resultType, context.getCachePerfStats());
+ set = QueryUtils.createResultCollection(context, resultType) ;
}
indexFieldsSize = 1;
}
@@ -427,11 +434,11 @@ public class CompiledComparison extends AbstractCompiledValue implements
context.getCache().getLogger().fine(
"StructType resultType.class="
+ resultType.getClass().getName());
- if(useLinkedSet) {
- set = new LinkedStructSet((StructTypeImpl)resultType);
+ if(useLinkedDataStructure) {
+ set = context.isDistinct() ? new LinkedStructSet((StructTypeImpl)resultType)
+ : new SortedResultsBag<Struct>((StructTypeImpl)resultType, nullValuesAtStart);
}else {
- set = new StructBag((StructTypeImpl)resultType,
- context.getCachePerfStats());
+ set = QueryUtils.createStructCollection(context,(StructTypeImpl)resultType) ;
}
indexFieldsSize = ((StructTypeImpl)resultType).getFieldNames().length;
}
@@ -439,10 +446,11 @@ public class CompiledComparison extends AbstractCompiledValue implements
context.getCache().getLogger().fine(
"non-StructType resultType.class="
+ resultType.getClass().getName());
- if (useLinkedSet) {
- set = new LinkedResultSet(resultType);
+ if (useLinkedDataStructure) {
+ set = context.isDistinct() ? new LinkedResultSet(resultType) :
+ new SortedResultsBag(resultType, nullValuesAtStart );
} else {
- set = new ResultsBag(resultType, context.getCachePerfStats());
+ set = QueryUtils.createResultCollection(context, resultType) ;
}
indexFieldsSize = 1;
}
@@ -458,11 +466,11 @@ public class CompiledComparison extends AbstractCompiledValue implements
if (resultType instanceof StructType) {
context.getCache().getLogger().fine(
"StructType resultType.class=" + resultType.getClass().getName());
- if (useLinkedSet) {
- set = new LinkedStructSet((StructTypeImpl)resultType);
+ if (useLinkedDataStructure) {
+ set = context.isDistinct() ? new LinkedStructSet((StructTypeImpl)resultType)
+ : new SortedResultsBag<Struct>((StructTypeImpl)resultType, nullValuesAtStart);
} else {
- set = (SelectResults)new StructBag((StructTypeImpl)resultType,
- context.getCachePerfStats());
+ set = QueryUtils.createStructCollection(context, (StructTypeImpl)resultType) ;
}
indexFieldsSize = ((StructTypeImpl)resultType).getFieldNames().length;
@@ -471,10 +479,11 @@ public class CompiledComparison extends AbstractCompiledValue implements
context.getCache().getLogger().fine(
"non-StructType resultType.class="
+ resultType.getClass().getName());
- if (useLinkedSet) {
- set = new LinkedResultSet(resultType);
+ if (useLinkedDataStructure) {
+ set = context.isDistinct() ? new LinkedResultSet(resultType) :
+ new SortedResultsBag(resultType, nullValuesAtStart);
} else {
- set = new ResultsBag(resultType, context.getCachePerfStats());
+ set = QueryUtils.createResultCollection(context, resultType) ;
}
indexFieldsSize = 1;
}