You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by to...@apache.org on 2015/04/13 21:18:09 UTC
[02/33] incubator-usergrid git commit: Removed obsolete query object.
Now a single utility builder and a ParsedQuery that represents our result
Removed obsolete query object. Now a single utility builder and a ParsedQuery that represents our result
Some tests are failing due to case sensitivity. This is due to indexing. This will be fixed later.
Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/2699dd30
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/2699dd30
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/2699dd30
Branch: refs/heads/two-dot-o-dev
Commit: 2699dd30fdf4bedb939a6eabfaef787a863121f6
Parents: 3c0a8a8
Author: Todd Nine <tn...@apigee.com>
Authored: Wed Apr 1 16:05:19 2015 -0600
Committer: Todd Nine <tn...@apigee.com>
Committed: Wed Apr 1 16:35:35 2015 -0600
----------------------------------------------------------------------
stack/corepersistence/pom.xml | 2 +-
.../index/query/tree/CpQueryFilter.g | 20 +-
.../index/ApplicationEntityIndex.java | 9 +-
.../usergrid/persistence/index/EntityIndex.java | 9 -
.../impl/EsApplicationEntityIndexImpl.java | 78 +-
.../impl/SearchRequestBuilderStrategy.java | 37 +-
.../persistence/index/query/ParsedQuery.java | 204 +++
.../index/query/ParsedQueryBuilder.java | 108 ++
.../usergrid/persistence/index/query/Query.java | 1432 ------------------
.../index/query/SelectFieldMapping.java | 55 +
.../persistence/index/query/SortPredicate.java | 126 ++
.../persistence/index/impl/EntityIndexTest.java | 334 ++--
.../index/impl/IndexLoadTestsIT.java | 5 +-
.../persistence/query/tree/GrammarTreeTest.java | 155 +-
14 files changed, 838 insertions(+), 1736 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/pom.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/pom.xml b/stack/corepersistence/pom.xml
index 3ec7852..b8227f7 100644
--- a/stack/corepersistence/pom.xml
+++ b/stack/corepersistence/pom.xml
@@ -50,7 +50,7 @@ limitations under the License.
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
- <antlr.version>3.4</antlr.version>
+ <antlr.version>3.5.2</antlr.version>
<archaius.version>0.5.12</archaius.version>
<astyanax.version>1.56.49-SNAPSHOT-UG-1</astyanax.version>
<cassandra.version>1.2.18</cassandra.version>
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/antlr3/org/apache/usergrid/persistence/index/query/tree/CpQueryFilter.g
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/antlr3/org/apache/usergrid/persistence/index/query/tree/CpQueryFilter.g b/stack/corepersistence/queryindex/src/main/antlr3/org/apache/usergrid/persistence/index/query/tree/CpQueryFilter.g
index f1ae62f..605aed4 100644
--- a/stack/corepersistence/queryindex/src/main/antlr3/org/apache/usergrid/persistence/index/query/tree/CpQueryFilter.g
+++ b/stack/corepersistence/queryindex/src/main/antlr3/org/apache/usergrid/persistence/index/query/tree/CpQueryFilter.g
@@ -31,18 +31,20 @@ package org.apache.usergrid.persistence.index.query.tree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.apache.usergrid.persistence.index.query.Query.SortPredicate;
+import org.apache.usergrid.persistence.index.query.ParsedQuery;
+import org.apache.usergrid.persistence.index.query.SortPredicate;
}
@members {
- Query query = new Query();
private static final Logger logger = LoggerFactory
.getLogger(CpQueryFilterLexer.class);
+ //the object that represents a parsed query
+ private ParsedQuery parsedQuery = new ParsedQuery();
+
@Override
public void emitErrorMessage(String msg) {
logger.info(msg);
@@ -300,7 +302,7 @@ order
: (property direction?){
String property = $property.text;
String direction = $direction.text;
- query.addSort(new SortPredicate(property, direction));
+ parsedQuery.addSort(new SortPredicate(property, direction));
};
@@ -311,7 +313,7 @@ order
select_subject
: ID {
- query.addSelect($ID.text);
+ parsedQuery.addSelect($ID.text);
};
@@ -320,7 +322,7 @@ select_subject
select_assign
: target=ID ':' source=ID {
- query.addSelect($target.text, $source.text);
+ parsedQuery.addSelect($target.text, $source.text);
};
@@ -329,14 +331,14 @@ select_expr
//end select clauses
-ql returns [Query query]
+ql returns [ParsedQuery parsedQuery]
: ('select'! select_expr!)? ('where'!? expression)? ('order by'! order! (','! order!)*)? {
if($expression.tree instanceof Operand){
- query.setRootOperand((Operand)$expression.tree);
+ parsedQuery.setRootOperand((Operand)$expression.tree);
}
- retval.query = query;
+ retval.parsedQuery = parsedQuery;
};
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/ApplicationEntityIndex.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/ApplicationEntityIndex.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/ApplicationEntityIndex.java
index c78d6b6..595cd66 100644
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/ApplicationEntityIndex.java
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/ApplicationEntityIndex.java
@@ -19,8 +19,9 @@
*/
package org.apache.usergrid.persistence.index;
+
import org.apache.usergrid.persistence.index.query.CandidateResults;
-import org.apache.usergrid.persistence.index.query.Query;
+
import rx.Observable;
/**
@@ -34,11 +35,7 @@ public interface ApplicationEntityIndex {
*/
public EntityIndexBatch createBatch();
- /**
- * Execute query in Usergrid syntax.
- */
- public CandidateResults search(final IndexScope indexScope, final SearchTypes searchTypes, final Query query);
- public CandidateResults search(final IndexScope indexScope, final SearchTypes searchTypes, final Query query, final int limit);
+ public CandidateResults search(final IndexScope indexScope, final SearchTypes searchTypes, final String query, final int limit);
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java
index 54a4127..7693b61 100644
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java
@@ -19,18 +19,9 @@
package org.apache.usergrid.persistence.index;
-import java.util.UUID;
import org.apache.usergrid.persistence.core.CPManager;
import org.apache.usergrid.persistence.core.util.Health;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.apache.usergrid.persistence.index.query.CandidateResults;
-import org.apache.usergrid.persistence.model.entity.Id;
-import org.elasticsearch.action.ListenableActionFuture;
-import rx.Observable;
-
-import java.util.Map;
-import java.util.concurrent.Future;
/**
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsApplicationEntityIndexImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsApplicationEntityIndexImpl.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsApplicationEntityIndexImpl.java
index 25b926d..dfe1c85 100644
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsApplicationEntityIndexImpl.java
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsApplicationEntityIndexImpl.java
@@ -19,24 +19,12 @@
*/
package org.apache.usergrid.persistence.index.impl;
-import com.codahale.metrics.Meter;
-import com.codahale.metrics.Timer;
-import com.google.common.base.Preconditions;
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-import org.apache.usergrid.persistence.core.metrics.MetricsFactory;
-import org.apache.usergrid.persistence.core.scope.ApplicationScope;
-import org.apache.usergrid.persistence.core.util.ValidationUtils;
-import org.apache.usergrid.persistence.index.*;
-import org.apache.usergrid.persistence.index.query.CandidateResult;
-import org.apache.usergrid.persistence.index.query.CandidateResults;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.apache.usergrid.persistence.map.MapManager;
-import org.apache.usergrid.persistence.map.MapManagerFactory;
-import org.apache.usergrid.persistence.map.MapScope;
-import org.apache.usergrid.persistence.map.impl.MapScopeImpl;
-import org.apache.usergrid.persistence.model.entity.Id;
-import org.apache.usergrid.persistence.model.entity.SimpleId;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ListenableActionFuture;
import org.elasticsearch.action.ShardOperationFailedException;
@@ -45,17 +33,47 @@ import org.elasticsearch.action.deletebyquery.IndexDeleteByQueryResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequestBuilder;
-import org.elasticsearch.index.query.*;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import rx.Observable;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
+import org.apache.usergrid.persistence.core.metrics.MetricsFactory;
+import org.apache.usergrid.persistence.core.scope.ApplicationScope;
+import org.apache.usergrid.persistence.core.util.ValidationUtils;
+import org.apache.usergrid.persistence.index.AliasedEntityIndex;
+import org.apache.usergrid.persistence.index.ApplicationEntityIndex;
+import org.apache.usergrid.persistence.index.EntityIndexBatch;
+import org.apache.usergrid.persistence.index.IndexAlias;
+import org.apache.usergrid.persistence.index.IndexBufferProducer;
+import org.apache.usergrid.persistence.index.IndexCache;
+import org.apache.usergrid.persistence.index.IndexFig;
+import org.apache.usergrid.persistence.index.IndexIdentifier;
+import org.apache.usergrid.persistence.index.IndexScope;
+import org.apache.usergrid.persistence.index.SearchTypes;
+import org.apache.usergrid.persistence.index.query.CandidateResult;
+import org.apache.usergrid.persistence.index.query.CandidateResults;
+import org.apache.usergrid.persistence.index.query.ParsedQuery;
+import org.apache.usergrid.persistence.index.query.ParsedQueryBuilder;
+import org.apache.usergrid.persistence.map.MapManager;
+import org.apache.usergrid.persistence.map.MapManagerFactory;
+import org.apache.usergrid.persistence.map.MapScope;
+import org.apache.usergrid.persistence.map.impl.MapScopeImpl;
+import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.entity.SimpleId;
+
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.Timer;
+import com.google.common.base.Preconditions;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
-import static org.apache.usergrid.persistence.index.impl.IndexingUtils.*;
+import rx.Observable;
+
+import static org.apache.usergrid.persistence.index.impl.IndexingUtils.APPLICATION_ID_FIELDNAME;
import static org.apache.usergrid.persistence.index.impl.IndexingUtils.SPLITTER;
/**
@@ -123,19 +141,15 @@ public class EsApplicationEntityIndexImpl implements ApplicationEntityIndex{
}
@Override
- public CandidateResults search(final IndexScope indexScope, final SearchTypes searchTypes, final Query query) {
- return search(indexScope,searchTypes,query,query.getLimit());
- }
- @Override
- public CandidateResults search(final IndexScope indexScope, final SearchTypes searchTypes, final Query query, final int limit){
+ public CandidateResults search( final IndexScope indexScope, final SearchTypes searchTypes, final String query,
+ final int limit ) {
- if(query.getCursor()!=null){
- return getNextPage(query.getCursor(), query.getLimit());
- }
SearchResponse searchResponse;
- SearchRequestBuilder srb = searchRequest.getBuilder(indexScope, searchTypes, query,limit);
+ final ParsedQuery parsedQuery = ParsedQueryBuilder.build( query );
+
+ final SearchRequestBuilder srb = searchRequest.getBuilder(indexScope, searchTypes, parsedQuery,limit);
if (logger.isDebugEnabled()) {
logger.debug("Searching index (read alias): {}\n scope: {} \n type: {}\n query: {} ",
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/SearchRequestBuilderStrategy.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/SearchRequestBuilderStrategy.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/SearchRequestBuilderStrategy.java
index 207a7a8..8a378b8 100644
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/SearchRequestBuilderStrategy.java
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/SearchRequestBuilderStrategy.java
@@ -19,13 +19,7 @@
*/
package org.apache.usergrid.persistence.index.impl;
-import com.google.common.base.Preconditions;
-import org.apache.usergrid.persistence.core.scope.ApplicationScope;
-import org.apache.usergrid.persistence.core.util.ValidationUtils;
-import org.apache.usergrid.persistence.index.*;
-import org.apache.usergrid.persistence.index.exceptions.IndexException;
-import org.apache.usergrid.persistence.index.query.Query;
-import org.apache.usergrid.persistence.index.query.tree.QueryVisitor;
+
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.FilterBuilder;
@@ -37,7 +31,22 @@ import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static org.apache.usergrid.persistence.index.impl.IndexingUtils.*;
+import org.apache.usergrid.persistence.core.scope.ApplicationScope;
+import org.apache.usergrid.persistence.index.EntityIndex;
+import org.apache.usergrid.persistence.index.IndexAlias;
+import org.apache.usergrid.persistence.index.IndexScope;
+import org.apache.usergrid.persistence.index.SearchTypes;
+import org.apache.usergrid.persistence.index.exceptions.IndexException;
+import org.apache.usergrid.persistence.index.query.ParsedQuery;
+import org.apache.usergrid.persistence.index.query.SortPredicate;
+import org.apache.usergrid.persistence.index.query.tree.QueryVisitor;
+
+import com.google.common.base.Preconditions;
+
+import static org.apache.usergrid.persistence.index.impl.IndexingUtils.BOOLEAN_PREFIX;
+import static org.apache.usergrid.persistence.index.impl.IndexingUtils.DOUBLE_PREFIX;
+import static org.apache.usergrid.persistence.index.impl.IndexingUtils.LONG_PREFIX;
+import static org.apache.usergrid.persistence.index.impl.IndexingUtils.STRING_PREFIX;
import static org.apache.usergrid.persistence.index.impl.IndexingUtils.createContextName;
import static org.apache.usergrid.persistence.index.impl.IndexingUtils.createLegacyContextName;
@@ -62,7 +71,7 @@ public class SearchRequestBuilderStrategy {
this.cursorTimeout = cursorTimeout;
}
- public SearchRequestBuilder getBuilder(final IndexScope indexScope, final SearchTypes searchTypes, final Query query, final int limit) {
+ public SearchRequestBuilder getBuilder(final IndexScope indexScope, final SearchTypes searchTypes, final ParsedQuery query, final int limit) {
Preconditions.checkArgument(limit <= EntityIndex.MAX_LIMIT, "limit is greater than max "+ EntityIndex.MAX_LIMIT);
@@ -82,10 +91,10 @@ public class SearchRequestBuilderStrategy {
srb = srb.setFrom(0).setSize(limit);
- for (Query.SortPredicate sp : query.getSortPredicates()) {
+ for (SortPredicate sp : query.getSortPredicates()) {
final SortOrder order;
- if (sp.getDirection().equals(Query.SortDirection.ASCENDING)) {
+ if (sp.getDirection().equals( SortPredicate.SortDirection.ASCENDING)) {
order = SortOrder.ASC;
} else {
order = SortOrder.DESC;
@@ -127,7 +136,7 @@ public class SearchRequestBuilderStrategy {
}
- public QueryBuilder createQueryBuilder( IndexScope indexScope, Query query) {
+ public QueryBuilder createQueryBuilder( IndexScope indexScope, ParsedQuery query) {
String[] contexts = new String[]{createContextName(applicationScope, indexScope),createLegacyContextName(applicationScope,indexScope)};
QueryBuilder queryBuilder = null;
@@ -161,7 +170,7 @@ public class SearchRequestBuilderStrategy {
for(String context : contexts){
boolQueryBuilder = boolQueryBuilder.should(QueryBuilders.termQuery( IndexingUtils.ENTITY_CONTEXT_FIELDNAME, context ));
}
- boolQueryBuilder = boolQueryBuilder.minimumNumberShouldMatch(1);
+ boolQueryBuilder = boolQueryBuilder.minimumNumberShouldMatch( 1 );
if ( queryBuilder != null ) {
queryBuilder = boolQueryBuilder.must( queryBuilder );
}
@@ -175,7 +184,7 @@ public class SearchRequestBuilderStrategy {
}
- public FilterBuilder createFilterBuilder(Query query) {
+ public FilterBuilder createFilterBuilder(ParsedQuery query) {
FilterBuilder filterBuilder = null;
if ( query.getRootOperand() != null ) {
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQuery.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQuery.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQuery.java
new file mode 100644
index 0000000..a55f8ea
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQuery.java
@@ -0,0 +1,204 @@
+/*
+ *
+ * *
+ * * Licensed to the Apache Software Foundation (ASF) under one
+ * * or more contributor license agreements. See the NOTICE file
+ * * distributed with this work for additional information
+ * * regarding copyright ownership. The ASF licenses this file
+ * * to you under the Apache License, Version 2.0 (the
+ * * "License"); you may not use this file except in compliance
+ * * with the License. You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an
+ * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * * KIND, either express or implied. See the License for the
+ * * specific language governing permissions and limitations
+ * * under the License.
+ * *
+ *
+ */
+
+package org.apache.usergrid.persistence.index.query;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.usergrid.persistence.index.exceptions.QueryParseException;
+import org.apache.usergrid.persistence.index.query.tree.Operand;
+
+
+/**
+ * Our object that represents our parsed query
+ */
+public class ParsedQuery {
+
+ //fast lookup for our sort predicates
+ private Set<String> sortPropertyNames = new HashSet<>();
+
+ //The sort predicates ordered by their input order in the grammar
+ private List<SortPredicate> sortPredicateList = new ArrayList<>();
+
+ /**
+ * Our map that contains field mappings
+ */
+ private Map<String, SelectFieldMapping> fieldMappings = new HashMap<>();
+
+ /**
+ * The root operand of our query
+ */
+ private Operand rootOperand;
+
+ private String originalQuery;
+
+
+ /**
+ * Get the original query
+ * @return
+ */
+ public String getOriginalQuery() {
+ return originalQuery;
+ }
+
+
+ /**
+ * Set the original query
+ * @param originalQuery
+ */
+ public void setOriginalQuery( final String originalQuery ) {
+ this.originalQuery = originalQuery;
+ }
+
+
+ /**
+ * Set the root operand of our query tree
+ * @param rootOperand
+ * @return
+ */
+ public ParsedQuery setRootOperand(final Operand rootOperand){
+ this.rootOperand = rootOperand;
+
+ return this;
+ }
+
+
+ /**
+ * Get our field mappings from the parsed query
+ * @return
+ */
+ public Collection<SelectFieldMapping> getSelectFieldMappings(){
+ return fieldMappings.values();
+ }
+
+ /**
+ * Add a sort predicate to our list
+ */
+ public ParsedQuery addSort( final SortPredicate sort ) {
+ if ( sort == null ) {
+ return this;
+ }
+
+ final String sortPropertyName = sort.getPropertyName();
+
+ if ( sortPropertyNames.contains( sortPropertyName ) ) {
+ throw new QueryParseException(
+ String.format( "Attempted to set sort order for %s more than once", sort.getPropertyName() ) );
+ }
+
+
+ sortPredicateList.add( sort );
+ sortPropertyNames.add( sortPropertyName );
+
+ return this;
+ }
+
+
+ /**
+ * Get the list of sort predicates
+ * @return
+ */
+ public List<SortPredicate> getSortPredicates() {
+ return sortPredicateList;
+ }
+
+
+ /**
+ * Possiblly add a single select to our results
+ */
+ public ParsedQuery addSelect( final String select ) {
+
+ final String normalizedSelect = getSelect( select );
+
+ if ( normalizedSelect == null ) {
+ return this;
+ }
+
+ fieldMappings.put( select, new SelectFieldMapping( normalizedSelect, normalizedSelect ) );
+
+ return this;
+ }
+
+
+ /**
+ * Use this when the user does a "select id:mynewidname " in the select clause of the grammar
+ * @param select
+ * @param output
+ * @return
+ */
+ public ParsedQuery addSelect( final String select, final String output ) {
+ final String normalizedSelect = getSelect( select );
+
+ if ( normalizedSelect == null ) {
+ return this;
+ }
+
+ final String normalizedOutput = getSelect( output );
+
+ if ( normalizedOutput == null ) {
+ return this;
+ }
+
+
+ fieldMappings.put( select, new SelectFieldMapping( normalizedSelect, normalizedOutput ) );
+
+ return this;
+ }
+
+
+ /**
+ * Get the field for select. This trims the field and validates the input. If the field is not valid, null willl
+ * be returned. If null is returned, the caller should short circuit.
+ */
+ private String getSelect( final String select ) {
+ // be paranoid with the null checks because
+ // the query parser sometimes flakes out
+ if ( select == null ) {
+ return null;
+ }
+
+ final String trimmedSelect = select.trim();
+
+ if ( trimmedSelect.equals( "*" ) ) {
+ return null;
+ }
+
+ return trimmedSelect;
+ }
+
+
+ /**
+ * Get the root operand
+ * @return
+ */
+ public Operand getRootOperand() {
+ return rootOperand;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQueryBuilder.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQueryBuilder.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQueryBuilder.java
new file mode 100644
index 0000000..3498f3c
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/ParsedQueryBuilder.java
@@ -0,0 +1,108 @@
+/*
+ *
+ * *
+ * * Licensed to the Apache Software Foundation (ASF) under one
+ * * or more contributor license agreements. See the NOTICE file
+ * * distributed with this work for additional information
+ * * regarding copyright ownership. The ASF licenses this file
+ * * to you under the Apache License, Version 2.0 (the
+ * * "License"); you may not use this file except in compliance
+ * * with the License. You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an
+ * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * * KIND, either express or implied. See the License for the
+ * * specific language governing permissions and limitations
+ * * under the License.
+ * *
+ *
+ */
+
+package org.apache.usergrid.persistence.index.query;
+
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.Token;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.commons.lang.StringUtils;
+
+import org.apache.usergrid.persistence.index.exceptions.QueryParseException;
+import org.apache.usergrid.persistence.index.query.tree.CpQueryFilterLexer;
+import org.apache.usergrid.persistence.index.query.tree.CpQueryFilterParser;
+
+
+/**
+ * A utility class that will parse our query, then return it's parsed representation
+ */
+public class ParsedQueryBuilder {
+
+ private static final Logger logger = LoggerFactory.getLogger( ParsedQueryBuilder.class );
+
+
+ /**
+ * Generate a parsedQuery from the ql
+ */
+ public static ParsedQuery build( final String ql ) throws QueryParseException {
+ if ( StringUtils.isEmpty( ql ) ) {
+ return null;
+ }
+ logger.debug( "Processing raw query: " + ql );
+
+ final String trimmedLowercaseQuery = ql.trim().toLowerCase();
+
+
+ //the output query after post processing
+ final String outputQuery;
+
+ //it doesn't start with select, rewrite it to be a correct query grammar
+ if ( !trimmedLowercaseQuery.startsWith( "select" ) ) {
+
+ //just an order by, add the select
+ //just starts with a where, add the select
+ if ( trimmedLowercaseQuery.startsWith( "order by" ) || trimmedLowercaseQuery.startsWith( "where" )) {
+ outputQuery = "select * " + trimmedLowercaseQuery;
+ }
+
+
+ //junk, bail
+ else {
+ outputQuery = "select * where" + trimmedLowercaseQuery;
+ }
+ }
+ else {
+ outputQuery = trimmedLowercaseQuery;
+ }
+
+ ANTLRStringStream in = new ANTLRStringStream( outputQuery );
+ CpQueryFilterLexer lexer = new CpQueryFilterLexer( in );
+ CommonTokenStream tokens = new CommonTokenStream( lexer );
+ CpQueryFilterParser parser = new CpQueryFilterParser( tokens );
+
+
+ try {
+ final ParsedQuery query = parser.ql().parsedQuery;
+ query.setOriginalQuery( ql );
+ return query;
+ }
+ catch ( RecognitionException e ) {
+ logger.error( "Unable to parse \"{}\"", ql, e );
+
+ int index = e.index;
+ int lineNumber = e.line;
+ Token token = e.token;
+
+ String message = String.format(
+ "The query cannot be parsed. The token '%s' at " + "column %d on line %d cannot be " + "parsed",
+ token.getText(), index, lineNumber );
+
+ throw new QueryParseException( message, e );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Query.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Query.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Query.java
deleted file mode 100644
index 5567382..0000000
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Query.java
+++ /dev/null
@@ -1,1432 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.usergrid.persistence.index.query;
-
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.UUID;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import java.io.IOException;
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.ClassicToken;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.RecognitionException;
-import org.antlr.runtime.Token;
-import org.antlr.runtime.TokenRewriteStream;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.lang.StringUtils;
-import org.apache.usergrid.persistence.index.exceptions.IndexException;
-import org.apache.usergrid.persistence.index.exceptions.QueryParseException;
-import org.apache.usergrid.persistence.index.impl.EsQueryVistor;
-import org.apache.usergrid.persistence.index.impl.IndexingUtils;
-import org.apache.usergrid.persistence.index.query.tree.AndOperand;
-import org.apache.usergrid.persistence.index.query.tree.ContainsOperand;
-import org.apache.usergrid.persistence.index.query.tree.CpQueryFilterLexer;
-import org.apache.usergrid.persistence.index.query.tree.CpQueryFilterParser;
-import org.apache.usergrid.persistence.index.query.tree.Equal;
-import org.apache.usergrid.persistence.index.query.tree.EqualityOperand;
-import org.apache.usergrid.persistence.index.query.tree.GreaterThan;
-import org.apache.usergrid.persistence.index.query.tree.GreaterThanEqual;
-import org.apache.usergrid.persistence.index.query.tree.LessThan;
-import org.apache.usergrid.persistence.index.query.tree.LessThanEqual;
-import org.apache.usergrid.persistence.index.query.tree.Operand;
-import org.apache.usergrid.persistence.index.query.tree.QueryVisitor;
-import org.apache.usergrid.persistence.index.utils.ClassUtils;
-import org.apache.usergrid.persistence.index.utils.ConversionUtils;
-import org.apache.usergrid.persistence.index.utils.ListUtils;
-import org.apache.usergrid.persistence.index.utils.MapUtils;
-import org.elasticsearch.index.query.FilterBuilder;
-import org.elasticsearch.index.query.QueryBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * TODO, this is a copy from 1.0 and a mess. Clean this up to be clearer as we iterate on our refactor of EM/RM
- * Query should only be used for term querying, not identity of name lookup, that should
- * come directly from cassandra
- */
-public class Query {
- private static final Logger logger = LoggerFactory.getLogger( Query.class );
-
- public enum Level {
- IDS, REFS, CORE_PROPERTIES, ALL_PROPERTIES, LINKED_PROPERTIES
- }
-
- public static final int DEFAULT_LIMIT = 10;
-
- public static final int MAX_LIMIT = 1000;
-
- public static final String PROPERTY_UUID = "uuid";
-
- private String type;
- private List<SortPredicate> sortPredicates = new ArrayList<SortPredicate>();
- private Operand rootOperand;
- private UUID startResult;
- private String cursor;
- private int limit = 0;
-
- private Map<String, String> selectAssignments = new LinkedHashMap<String, String>();
- private boolean mergeSelectResults = false;
- private Level level = Level.ALL_PROPERTIES;
- private String connectionType;
- private List<String> permissions;
- private boolean reversed;
- private boolean reversedSet = false;
- private Long startTime;
- private Long finishTime;
- private boolean pad;
- private CounterResolution resolution = CounterResolution.ALL;
- private List<Identifier> identifiers;
- private List<CounterFilterPredicate> counterFilters;
- private String collection;
- private String ql;
-
- private static ObjectMapper mapper = new ObjectMapper();
-
-
- List<Operand> filterClauses = new ArrayList<Operand>();
-
- public Query() {
- }
-
-
- /**
- * Creates a deep copy of a query from another query
- * @param q
- */
- public Query( Query q ) {
- if ( q == null ) {
- return;
- }
-
- type = q.type;
- sortPredicates = q.sortPredicates != null
- ? new ArrayList<>( q.sortPredicates ) : null;
- startResult = q.startResult;
- cursor = q.cursor;
- limit = q.limit;
- selectAssignments = q.selectAssignments != null
- ? new LinkedHashMap<>( q.selectAssignments ) : null;
- mergeSelectResults = q.mergeSelectResults;
- //level = q.level;
- connectionType = q.connectionType;
- permissions = q.permissions != null ? new ArrayList<>( q.permissions ) : null;
- reversed = q.reversed;
- reversedSet = q.reversedSet;
- startTime = q.startTime;
- finishTime = q.finishTime;
- resolution = q.resolution;
- pad = q.pad;
- rootOperand = q.rootOperand;
- identifiers = q.identifiers != null
- ? new ArrayList<>( q.identifiers ) : null;
- counterFilters = q.counterFilters != null
- ? new ArrayList<>( q.counterFilters ) : null;
- collection = q.collection;
- level = q.level;
-
- }
-
-
- public QueryBuilder createQueryBuilder( final String context ) {
-
-
- QueryBuilder queryBuilder = null;
-
-
- //we have a root operand. Translate our AST into an ES search
- if ( getRootOperand() != null ) {
- // In the case of geo only queries, this will return null into the query builder.
- // Once we start using tiles, we won't need this check any longer, since a geo query
- // will return a tile query + post filter
- QueryVisitor v = new EsQueryVistor();
-
- try {
- getRootOperand().visit( v );
- }
- catch ( IndexException ex ) {
- throw new RuntimeException( "Error building ElasticSearch query", ex );
- }
-
-
- queryBuilder = v.getQueryBuilder();
- }
-
-
- // Add our filter for context to our query for fast execution.
- // Fast because it utilizes bitsets internally. See this post for more detail.
- // http://www.elasticsearch.org/blog/all-about-elasticsearch-filter-bitsets/
-
- // TODO evaluate performance when it's an all query.
- // Do we need to put the context term first for performance?
- if ( queryBuilder != null ) {
- queryBuilder = QueryBuilders.boolQuery().must( queryBuilder ).must( QueryBuilders
- .termQuery( IndexingUtils.ENTITY_CONTEXT_FIELDNAME, context ) );
- }
-
- //nothing was specified ensure we specify the context in the search
- else {
- queryBuilder = QueryBuilders.termQuery( IndexingUtils.ENTITY_CONTEXT_FIELDNAME, context );
- }
-
- return queryBuilder;
- }
-
-
- public FilterBuilder createFilterBuilder() {
- FilterBuilder filterBuilder = null;
-
- if ( getRootOperand() != null ) {
- QueryVisitor v = new EsQueryVistor();
- try {
- getRootOperand().visit( v );
-
- } catch ( IndexException ex ) {
- throw new RuntimeException( "Error building ElasticSearch query", ex );
- }
- filterBuilder = v.getFilterBuilder();
- }
-
- return filterBuilder;
- }
-
-
- /**
- * Create a query instance from the QL. If the string is null, return an empty query
- * @param ql
- * @return
- */
- public static Query fromQLNullSafe(final String ql){
- final Query query = fromQL(ql);
-
- if(query != null){
- return query;
- }
-
- return new Query();
- }
-
- public static Query fromQL( String ql ) throws QueryParseException {
- if ( StringUtils.isEmpty(ql) ) {
- return null;
- }
- logger.debug("Processing raw query: " + ql);
- String originalQl = ql;
- ql = ql.trim();
-
- String qlt = ql.toLowerCase();
- if ( !qlt.startsWith( "select" )
- && !qlt.startsWith( "insert" )
- && !qlt.startsWith( "update" ) && !qlt.startsWith( "delete" ) ) {
-
- if ( qlt.startsWith( "order by" ) ) {
- ql = "select * " + ql;
- }
- else {
- ql = "select * where " + ql;
- }
- }
-
- ANTLRStringStream in = new ANTLRStringStream( ql.trim().toLowerCase() );
- CpQueryFilterLexer lexer = new CpQueryFilterLexer( in );
- CommonTokenStream tokens = new CommonTokenStream( lexer );
- CpQueryFilterParser parser = new CpQueryFilterParser( tokens );
-
- try {
- Query q = parser.ql().query;
- q.setQl( originalQl );
- return q;
- }
- catch ( RecognitionException e ) {
- logger.error( "Unable to parse \"{}\"", ql, e );
-
- int index = e.index;
- int lineNumber = e.line;
- Token token = e.token;
-
- String message = String.format("The query cannot be parsed. The token '%s' at "
- + "column %d on line %d cannot be " + "parsed", token.getText(), index, lineNumber);
-
- throw new QueryParseException( message, e );
- }
- }
-
-
- private static Query newQueryIfNull( Query query ) {
- if ( query == null ) {
- query = new Query();
- }
- return query;
- }
-
-
- public static Query fromJsonString( String json ) throws QueryParseException {
-
- Object o;
- try {
- o = mapper.readValue( json, Object.class );
- } catch (IOException ex) {
- throw new QueryParseException("Error parsing JSON query string " + json, ex);
- }
-
- if ( o instanceof Map ) {
- @SuppressWarnings({ "unchecked", "rawtypes" }) Map<String, List<String>> params =
- ClassUtils.cast( MapUtils.toMapList( ( Map ) o ) );
- return fromQueryParams( params );
- }
- return null;
- }
-
-
- public static Query fromQueryParams( Map<String, List<String>> params )
- throws QueryParseException {
- Query q = null;
- CounterResolution resolution = null;
- List<Identifier> identifiers = null;
- List<CounterFilterPredicate> counterFilters = null;
-
- String ql = QueryUtils.queryStrFrom( params );
- String type = ListUtils.first( params.get( "type" ) );
- Boolean reversed = ListUtils.firstBoolean( params.get( "reversed" ) );
- String connection = ListUtils.first( params.get( "connectionType" ) );
- UUID start = ListUtils.firstUuid( params.get( "start" ) );
- String cursor = ListUtils.first( params.get( "cursor" ) );
- Integer limit = ListUtils.firstInteger( params.get( "limit" ) );
- List<String> permissions = params.get( "permission" );
- Long startTime = ListUtils.firstLong( params.get( "start_time" ) );
- Long finishTime = ListUtils.firstLong( params.get( "end_time" ) );
-
- List<String> l = params.get( "resolution" );
- if ( !ListUtils.isEmpty( l ) ) {
- resolution = CounterResolution.fromString( l.get( 0 ) );
- }
-
- l = params.get( "counter" );
-
- if ( !ListUtils.isEmpty( l ) ) {
- counterFilters = CounterFilterPredicate.fromList( l );
- }
-
- Boolean pad = ListUtils.firstBoolean( params.get( "pad" ) );
-
- for ( Entry<String, List<String>> param : params.entrySet() ) {
- Identifier identifier = Identifier.from( param.getKey() );
- if ( ( param.getValue() == null ) || ( param.getValue().size() == 0 ) || identifier.isUUID() ) {
- if ( identifier != null ) {
- if ( identifiers == null ) {
- identifiers = new ArrayList<Identifier>();
- }
- identifiers.add( identifier );
- }
- }
- }
-
- if ( ql != null ) {
- q = Query.fromQL( decode( ql ) );
- }
-
- l = params.get( "filter" );
-
- if ( !ListUtils.isEmpty( l ) ) {
- q = newQueryIfNull( q );
- for ( String s : l ) {
- q.addFilter( decode( s ) );
- }
- }
-
- l = params.get( "sort" );
- if ( !ListUtils.isEmpty( l ) ) {
- q = newQueryIfNull( q );
- for ( String s : l ) {
- q.addSort( decode( s ) );
- }
- }
-
- if ( type != null ) {
- q = newQueryIfNull( q );
- q.setEntityType( type );
- }
-
- if ( connection != null ) {
- q = newQueryIfNull( q );
- q.setConnectionType( connection );
- }
-
- if ( permissions != null ) {
- q = newQueryIfNull( q );
- q.setPermissions( permissions );
- }
-
- if ( start != null ) {
- q = newQueryIfNull( q );
- q.setStartResult( start );
- }
-
- if ( cursor != null ) {
- q = newQueryIfNull( q );
- q.setCursor( cursor );
- }
-
- if ( limit != null ) {
- q = newQueryIfNull( q );
- q.setLimit( limit );
- }
-
- if ( startTime != null ) {
- q = newQueryIfNull( q );
- q.setStartTime( startTime );
- }
-
- if ( finishTime != null ) {
- q = newQueryIfNull( q );
- q.setFinishTime( finishTime );
- }
-
- if ( resolution != null ) {
- q = newQueryIfNull( q );
- q.setResolution( resolution );
- }
-
- if ( counterFilters != null ) {
- q = newQueryIfNull( q );
- q.setCounterFilters( counterFilters );
- }
-
- if ( pad != null ) {
- q = newQueryIfNull( q );
- q.setPad( pad );
- }
-
- if ( identifiers != null ) {
- q = newQueryIfNull( q );
- q.setIdentifiers( identifiers );
- }
-
- if ( reversed != null ) {
- q = newQueryIfNull( q );
- q.setReversed( reversed );
- }
-
- return q;
- }
-
-
- public static Query searchForProperty( String propertyName, Object propertyValue ) {
- Query q = new Query();
- q.addEqualityFilter( propertyName, propertyValue );
- return q;
- }
-
-
- public static Query findForProperty( String propertyName, Object propertyValue ) {
- Query q = new Query();
- q.addEqualityFilter( propertyName, propertyValue );
- q.setLimit( 1 );
- return q;
- }
-
-
- public static Query fromUUID( UUID uuid ) {
- Query q = new Query();
- q.addIdentifier( Identifier.fromUUID( uuid ) );
- return q;
- }
-
-
- public static Query fromIdentifier( Object id ) {
- Query q = new Query();
- q.addIdentifier( Identifier.from( id ) );
- return q;
- }
-
-
- public boolean hasQueryPredicates() {
- return rootOperand != null;
- }
-
-
- public boolean containsNameOrEmailIdentifiersOnly() {
- if ( hasQueryPredicates() ) {
- return false;
- }
- if ( ( identifiers == null ) || identifiers.isEmpty() ) {
- return false;
- }
- for ( Identifier identifier : identifiers ) {
- if ( !identifier.isEmail() && !identifier.isName() ) {
- return false;
- }
- }
- return true;
- }
-
-
- @JsonIgnore
- public String getSingleNameOrEmailIdentifier() {
- if ( !containsSingleNameOrEmailIdentifier() ) {
- return null;
- }
- return ( identifiers.get( 0 ).toString() );
- }
-
-
- public boolean containsSingleNameOrEmailIdentifier() {
- return containsNameOrEmailIdentifiersOnly() && ( identifiers.size() == 1 );
- }
-
-
- @JsonIgnore
- public Identifier getSingleIdentifier() {
- return identifiers != null && identifiers.size() == 1 ? identifiers.get( 0 ) : null;
- }
-
-
- public boolean containsSingleUuidIdentifier() {
- return containsUuidIdentifiersOnly() && ( identifiers.size() == 1 );
- }
-
-
- boolean containsUuidIdentifiersOnly() {
- if ( hasQueryPredicates() ) {
- return false;
- }
- if ( ( identifiers == null ) || identifiers.isEmpty() ) {
- return false;
- }
-
- for ( Identifier identifier : identifiers ) {
- if ( !identifier.isUUID() ) {
- return false;
- }
- }
- return true;
- }
-
-
- @JsonIgnore
- public UUID getSingleUuidIdentifier() {
- if ( !containsSingleUuidIdentifier() ) {
- return null;
- }
- return ( identifiers.get( 0 ).getUUID() );
- }
-
-
- @JsonIgnore
- boolean isIdsOnly() {
- if ( ( selectAssignments.size() == 1 ) && selectAssignments.containsKey( PROPERTY_UUID ) ) {
- level = Level.IDS;
- return true;
- }
- return false;
- }
-
- private void setIdsOnly( boolean idsOnly ) {
- if ( idsOnly ) {
- selectAssignments = new LinkedHashMap<String, String>();
- selectAssignments.put( PROPERTY_UUID, PROPERTY_UUID );
- level = Level.IDS;
- }
- else if ( isIdsOnly() ) {
- selectAssignments = new LinkedHashMap<String, String>();
- level = Level.ALL_PROPERTIES;
- }
- }
-
-
- public Level getResultsLevel() {
- isIdsOnly();
- return level;
- }
-
-
- public void setResultsLevel( Level level ) {
- setIdsOnly( level == Level.IDS );
- this.level = level;
- }
-
-
- public Query withResultsLevel( Level level ) {
- setIdsOnly( level == Level.IDS );
- this.level = level;
- return this;
- }
-
-
- public Query withReversed( boolean reversed ) {
- setReversed( reversed );
- return this;
- }
-
-
- public String getEntityType() {
- return type;
- }
-
-
- public void setEntityType( String type ) {
- this.type = type;
- }
-
- public List<String> getPermissions() {
- return permissions;
- }
-
-
- public void setPermissions( List<String> permissions ) {
- this.permissions = permissions;
- }
-
-
- public Query addSelect( String select ) {
-
- return addSelect( select, null );
- }
-
-
- public Query addSelect( String select, String output ) {
- // be paranoid with the null checks because
- // the query parser sometimes flakes out
- if ( select == null ) {
- return this;
- }
- select = select.trim();
-
- if ( select.equals( "*" ) ) {
- return this;
- }
-
- mergeSelectResults = StringUtils.isNotEmpty( output );
-
- if ( output == null ) {
- output = "";
- }
-
- selectAssignments.put( select, output );
-
- return this;
- }
-
-
- public boolean hasSelectSubjects() {
- return !selectAssignments.isEmpty();
- }
-
-
- @JsonIgnore
- public Set<String> getSelectSubjects() {
- return selectAssignments.keySet();
- }
-
-
- public Map<String, String> getSelectAssignments() {
- return selectAssignments;
- }
-
-
- public boolean isMergeSelectResults() {
- return mergeSelectResults;
- }
-
-
- public Query addSort( SortPredicate sort ) {
- if ( sort == null ) {
- return this;
- }
-
- for ( SortPredicate s : sortPredicates ) {
- if ( s.getPropertyName().equals( sort.getPropertyName() ) ) {
- throw new QueryParseException( String.format(
- "Attempted to set sort order for %s more than once", s.getPropertyName() ) );
- }
- }
- sortPredicates.add( sort );
- return this;
- }
-
-
- public Query addSort( String propertyName ) {
- if ( StringUtils.isBlank( propertyName ) ) {
- return this;
- }
- propertyName = propertyName.trim();
- if ( propertyName.indexOf( ',' ) >= 0 ) {
- String[] propertyNames = StringUtils.split( propertyName, ',' );
- for ( String s : propertyNames ) {
- addSort( s );
- }
- return this;
- }
-
- SortDirection direction = SortDirection.ASCENDING;
- if ( propertyName.indexOf( ' ' ) >= 0 ) {
- String[] parts = StringUtils.split( propertyName, ' ' );
- if ( parts.length > 1 ) {
- propertyName = parts[0];
- direction = SortDirection.find( parts[1] );
- }
- }
- else if ( propertyName.startsWith( "-" ) ) {
- propertyName = propertyName.substring( 1 );
- direction = SortDirection.DESCENDING;
- }
- else if ( propertyName.startsWith( "+" ) ) {
- propertyName = propertyName.substring( 1 );
- direction = SortDirection.ASCENDING;
- }
-
- return addSort( propertyName, direction );
- }
-
-
- public Query addSort( String propertyName, SortDirection direction ) {
- if ( StringUtils.isBlank( propertyName ) ) {
- return this;
- }
- propertyName = propertyName.trim();
- for ( SortPredicate s : sortPredicates ) {
- if ( s.getPropertyName().equals( propertyName ) ) {
- logger.error(
- "Attempted to set sort order for " + s.getPropertyName()
- + " more than once, discarding..." );
- return this;
- }
- }
- sortPredicates.add( new SortPredicate( propertyName, direction ) );
- return this;
- }
-
-
- @JsonIgnore
- public boolean isSortSet() {
- return !sortPredicates.isEmpty();
- }
-
-
- public List<SortPredicate> getSortPredicates() {
- return sortPredicates;
- }
-
-
- public Query addFilter( String filter ) {
-
- ANTLRStringStream in = new ANTLRStringStream( filter );
- CpQueryFilterLexer lexer = new CpQueryFilterLexer( in );
- TokenRewriteStream tokens = new TokenRewriteStream( lexer );
- CpQueryFilterParser parser = new CpQueryFilterParser( tokens );
- Operand root = null;
-
- try {
- root = parser.ql().query.getRootOperand();
- }
- catch ( RecognitionException e ) {
- // todo: should we create a specific Exception for this? checked?
- throw new RuntimeException( "Unknown operation: " + filter, e );
- }
-
- if ( root != null ) {
- addClause( root );
- }
-
- return this;
- }
-
-
- /** Add a less than filter to this query. && with existing clauses */
- public Query addLessThanFilter( String propName, Object value ) {
- LessThan equality = new LessThan( null );
-
- addClause( equality, propName, value );
-
- return this;
- }
-
-
- /** Add a less than equal filter to this query. && with existing clauses */
- public Query addLessThanEqualFilter( String propName, Object value ) {
- LessThanEqual equality = new LessThanEqual( null );
-
- addClause( equality, propName, value );
-
- return this;
- }
-
-
- /** Add a equal filter to this query. && with existing clauses */
- public Query addEqualityFilter( String propName, Object value ) {
- Equal equality = new Equal( new ClassicToken( 1, "=" ) );
-
- addClause( equality, propName, value );
-
- return this;
- }
-
-
- /** Add a greater than equal filter to this query. && with existing clauses */
- public Query addGreaterThanEqualFilter( String propName, Object value ) {
- GreaterThanEqual equality = new GreaterThanEqual( null );
-
- addClause( equality, propName, value );
-
- return this;
- }
-
-
- /** Add a less than filter to this query. && with existing clauses */
- public Query addGreaterThanFilter( String propName, Object value ) {
- GreaterThan equality = new GreaterThan( null );
-
- addClause( equality, propName, value );
-
- return this;
- }
-
-
- public Query addContainsFilter( String propName, String keyword ) {
- ContainsOperand equality = new ContainsOperand( new ClassicToken( 0, "contains" ) );
-
- equality.setProperty( propName );
- equality.setLiteral( keyword );
-
- addClause( equality );
-
- return this;
- }
-
-
- private void addClause( EqualityOperand equals, String propertyName, Object value ) {
- equals.setProperty( propertyName );
- equals.setLiteral( value );
- addClause( equals );
- }
-
-
- private void addClause( Operand clause ) {
- filterClauses.add(clause);
-
- if ( rootOperand == null ) {
- rootOperand = clause;
- return;
- }
-
- AndOperand and = new AndOperand();
- and.addChild( rootOperand );
- and.addChild( clause );
-
-
- // redirect the root to new && clause
- rootOperand = and;
-
- }
-
-
- @JsonIgnore
- public Operand getRootOperand() {
- if ( rootOperand == null ) { // attempt deserialization
- if ( ql != null ) {
- try {
- Query q = Query.fromQL( ql );
- rootOperand = q.rootOperand;
- }
- catch ( QueryParseException e ) {
- logger.error( "error parsing sql for rootOperand", e ); // shouldn't happen
- }
- }
- }
- return rootOperand;
- }
-
-
- public void setRootOperand( Operand root ) {
- this.rootOperand = root;
- }
-
-
- public List<Operand> getFilterClauses() {
- return filterClauses;
- }
-
-
- void setStartResult( UUID startResult ) {
- this.startResult = startResult;
- }
-
-
- public Query withStartResult( UUID startResult ) {
- this.startResult = startResult;
- return this;
- }
-
-
- public UUID getStartResult() {
- if ( ( startResult == null ) && ( cursor != null ) ) {
- byte[] cursorBytes = Base64.decodeBase64( cursor );
- if ( ( cursorBytes != null ) && ( cursorBytes.length == 16 ) ) {
- startResult = ConversionUtils.uuid( cursorBytes );
- }
- }
- return startResult;
- }
-
-
- public String getCursor() {
- return cursor;
- }
-
-
- public void setCursor( String cursor ) {
- this.cursor = cursor;
- }
-
-
- public Query withCursor( String cursor ) {
- setCursor( cursor );
- return this;
- }
-
-
- public int getLimit() {
- return getLimit( DEFAULT_LIMIT );
- }
-
-
- public int getLimit( int defaultLimit ) {
- if ( limit <= 0 ) {
- if ( defaultLimit > 0 ) {
- return defaultLimit;
- }
- else {
- return DEFAULT_LIMIT;
- }
- }
- return limit;
- }
-
-
- public void setLimit( int limit ) {
-
- // TODO tnine. After users have had time to change their query limits,
- // this needs to be uncommented and enforced.
- // if(limit > MAX_LIMIT){
- // throw new IllegalArgumentException(
- // String.format("Query limit must be <= to %d", MAX_LIMIT));
- // }
-
- if ( limit > MAX_LIMIT ) {
- limit = MAX_LIMIT;
- }
-
- this.limit = limit;
- }
-
-
- public Query withLimit( int limit ) {
- setLimit( limit );
- return this;
- }
-
-
- public boolean isReversed() {
- return reversed;
- }
-
-
- public void setReversed( boolean reversed ) {
- reversedSet = true;
- this.reversed = reversed;
- }
-
-
- public boolean isReversedSet() {
- return reversedSet;
- }
-
-
- public Long getStartTime() {
- return startTime;
- }
-
-
- public void setStartTime( Long startTime ) {
- this.startTime = startTime;
- }
-
-
- public Long getFinishTime() {
- return finishTime;
- }
-
-
- public void setFinishTime( Long finishTime ) {
- this.finishTime = finishTime;
- }
-
-
- public boolean isPad() {
- return pad;
- }
-
-
- public void setPad( boolean pad ) {
- this.pad = pad;
- }
-
-
- public void setResolution( CounterResolution resolution ) {
- this.resolution = resolution;
- }
-
-
- public CounterResolution getResolution() {
- return resolution;
- }
-
-
- public void addIdentifier( Identifier identifier ) {
- if ( identifiers == null ) {
- identifiers = new ArrayList<Identifier>();
- }
- identifiers.add( identifier );
- }
-
-
- void setIdentifiers( List<Identifier> identifiers ) {
- this.identifiers = identifiers;
- }
-
-
- public List<CounterFilterPredicate> getCounterFilters() {
- return counterFilters;
- }
-
-
- public void addCounterFilter( String counter ) {
- CounterFilterPredicate p = CounterFilterPredicate.fromString( counter );
- if ( p == null ) {
- return;
- }
- if ( counterFilters == null ) {
- counterFilters = new ArrayList<CounterFilterPredicate>();
- }
- counterFilters.add( p );
- }
-
-
- void setCounterFilters( List<CounterFilterPredicate> counterFilters ) {
- this.counterFilters = counterFilters;
- }
-
-
- @Override
- public String toString() {
- if ( ql != null ) {
- return ql;
- }
- StringBuilder s = new StringBuilder( "select " );
- if ( selectAssignments.isEmpty() ) {
- s.append( "*" );
- }
- else {
- if ( mergeSelectResults ) {
- s.append( "{ " );
- boolean first = true;
- for ( Map.Entry<String, String> select : selectAssignments.entrySet() ) {
- if ( !first ) {
- s.append( ", " );
- }
- s.append( select.getValue() ).append( " : " ).append( select.getKey() );
- first = false;
- }
- s.append( " }" );
- }
- else {
- boolean first = true;
- for ( String select : selectAssignments.keySet() ) {
- if ( !first ) {
- s.append( ", " );
- }
- s.append( select );
- first = false;
- }
- }
- }
- s.append( " from " );
- s.append( type );
- if ( !sortPredicates.isEmpty() ) {
- boolean first = true;
- s.append( " order by " );
- for ( SortPredicate sp : sortPredicates ) {
- if ( !first ) {
- s.append( ", " );
- }
- s.append( sp );
- first = false;
- }
- }
- // if (!filterPredicates.isEmpty()) {
- // s.append(" where ");
- // boolean first = true;
- // for (FilterPredicate f : filterPredicates) {
- // if (!first) {
- // s.append(" and ");
- // }
- // s.append(f.toString());
- // first = false;
- // }
- // }
- return s.toString();
- }
-
-
- public static enum SortDirection {
- ASCENDING, DESCENDING;
-
-
- public static SortDirection find( String s ) {
- if ( s == null ) {
- return ASCENDING;
- }
- s = s.toLowerCase();
- if ( s.startsWith( "asc" ) ) {
- return ASCENDING;
- }
- if ( s.startsWith( "des" ) ) {
- return DESCENDING;
- }
- if ( s.equals( "+" ) ) {
- return ASCENDING;
- }
- if ( s.equals( "-" ) ) {
- return DESCENDING;
- }
- return ASCENDING;
- }
- }
-
-
- public static final class SortPredicate implements Serializable {
- private static final long serialVersionUID = 1L;
- private final String propertyName;
- private final Query.SortDirection direction;
-
-
- public SortPredicate(@JsonProperty("propertyName") String propertyName,
- @JsonProperty("direction") Query.SortDirection direction ) {
-
- if ( propertyName == null ) {
- throw new NullPointerException( "Property name was null" );
- }
-
- if ( direction == null ) {
- direction = SortDirection.ASCENDING;
- }
-
- this.propertyName = propertyName.trim();
- this.direction = direction;
- }
-
-
- public SortPredicate( String propertyName, String direction ) {
- this( propertyName, SortDirection.find( direction ) );
- }
-
-
- public String getPropertyName() {
- return propertyName;
- }
-
-
- public Query.SortDirection getDirection() {
- return direction;
- }
-
-
- @Override
- public boolean equals( Object o ) {
- if ( this == o ) {
- return true;
- }
- if ( ( o == null ) || ( super.getClass() != o.getClass() ) ) {
- return false;
- }
-
- SortPredicate that = ( SortPredicate ) o;
-
- if ( direction != that.direction ) {
- return false;
- }
-
- return ( propertyName.equals( that.propertyName ) );
- }
-
-
- @Override
- public int hashCode() {
- int result = propertyName.hashCode();
- result = ( 31 * result ) + direction.hashCode();
- return result;
- }
-
-
- @Override
- public String toString() {
- return propertyName + ( ( direction == Query.SortDirection.DESCENDING ) ? " DESC" : "" );
- }
- }
-
-
- public static final class CounterFilterPredicate implements Serializable {
-
- private static final long serialVersionUID = 1L;
- private final String name;
- private final Identifier user;
- private final Identifier group;
- private final String queue;
- private final String category;
-
-
- public CounterFilterPredicate( String name, Identifier user, Identifier group, String queue, String category ) {
- this.name = name;
- this.user = user;
- this.group = group;
- this.queue = queue;
- this.category = category;
- }
-
-
- public Identifier getUser() {
- return user;
- }
-
-
- public Identifier getGroup() {
- return group;
- }
-
-
- public String getQueue() {
- return queue;
- }
-
-
- public String getCategory() {
- return category;
- }
-
-
- public String getName() {
- return name;
- }
-
-
- public static CounterFilterPredicate fromString( String s ) {
- Identifier user = null;
- Identifier group = null;
- String category = null;
- String name = null;
- String[] l = StringUtils.split( s, ':' );
-
- if ( l.length > 0 ) {
- if ( !"*".equals( l[0] ) ) {
- name = l[0];
- }
- }
-
- if ( l.length > 1 ) {
- if ( !"*".equals( l[1] ) ) {
- user = Identifier.from( l[1] );
- }
- }
-
- if ( l.length > 2 ) {
- if ( !"*".equals( l[2] ) ) {
- group = Identifier.from( l[3] );
- }
- }
-
- if ( l.length > 3 ) {
- if ( !"*".equals( l[3] ) ) {
- category = l[3];
- }
- }
-
- if ( ( user == null ) && ( group == null ) && ( category == null ) && ( name == null)) {
- return null;
- }
-
- return new CounterFilterPredicate( name, user, group, null, category );
- }
-
-
- public static List<CounterFilterPredicate> fromList( List<String> l ) {
- if ( ( l == null ) || ( l.size() == 0 ) ) {
- return null;
- }
- List<CounterFilterPredicate> counterFilters = new ArrayList<CounterFilterPredicate>();
- for ( String s : l ) {
- CounterFilterPredicate filter = CounterFilterPredicate.fromString( s );
- if ( filter != null ) {
- counterFilters.add( filter );
- }
- }
- if ( counterFilters.size() == 0 ) {
- return null;
- }
- return counterFilters;
- }
- }
-
-
-// public List<Object> getSelectionResults( Results rs ) {
-//
-// List<Entity> entities = rs.getEntities();
-// if ( entities == null ) {
-// return null;
-// }
-//
-// if ( !hasSelectSubjects() ) {
-// return cast( entities );
-// }
-//
-// List<Object> results = new ArrayList<Object>();
-//
-// for ( Entity entity : entities ) {
-// if ( isMergeSelectResults() ) {
-// boolean include = false;
-// Map<String, Object> result = new LinkedHashMap<String, Object>();
-// Map<String, String> selects = getSelectAssignments();
-// for ( Map.Entry<String, String> select : selects.entrySet() ) {
-// Object obj = JsonUtils.select( entity, select.getValue(), false );
-// if ( obj != null ) {
-// include = true;
-// }
-// result.put( select.getKey(), obj );
-// }
-// if ( include ) {
-// results.add( result );
-// }
-// }
-// else {
-// boolean include = false;
-// List<Object> result = new ArrayList<Object>();
-// Set<String> selects = getSelectSubjects();
-// for ( String select : selects ) {
-// Object obj = JsonUtils.select( entity, select );
-// if ( obj != null ) {
-// include = true;
-// }
-// result.add( obj );
-// }
-// if ( include ) {
-// results.add( result );
-// }
-// }
-// }
-//
-// if ( results.size() == 0 ) {
-// return null;
-// }
-//
-// return results;
-// }
-
-
-// public Object getSelectionResult( Results rs ) {
-// List<Object> r = getSelectionResults( rs );
-// if ( ( r != null ) && ( r.size() > 0 ) ) {
-// return r.get( 0 );
-// }
-// return null;
-// }
-
-
- private static String decode( String input ) {
- try {
- return URLDecoder.decode( input, "UTF-8" );
- }
- catch ( UnsupportedEncodingException e ) {
- // shouldn't happen, but just in case
- throw new RuntimeException( e );
- }
- }
-
-
- // note: very likely to be null
- public String getCollection() {
- return collection;
- }
-
-
- public void setCollection( String collection ) {
- this.collection = collection;
- }
-
-
- // may be null
- public String getQl() {
- return ql;
- }
-
-
- public Query setQl( String ql ) {
- this.ql = ql;
- return this;
- }
-
-
- /**
- * Get the connection type
- * @return
- */
- public String getConnectionType() {
- return connectionType;
- }
-
-
- /**
- * Set the connection type
- * @param connection
- * @return
- */
- public Query setConnectionType( final String connection ) {
- this.connectionType = connection;
- return this;
- }
-
-
- public String getType() {
- return type;
- }
-
-
- public Level getLevel() {
- return level;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SelectFieldMapping.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SelectFieldMapping.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SelectFieldMapping.java
new file mode 100644
index 0000000..88a2780
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SelectFieldMapping.java
@@ -0,0 +1,55 @@
+/*
+ *
+ * *
+ * * Licensed to the Apache Software Foundation (ASF) under one
+ * * or more contributor license agreements. See the NOTICE file
+ * * distributed with this work for additional information
+ * * regarding copyright ownership. The ASF licenses this file
+ * * to you under the Apache License, Version 2.0 (the
+ * * "License"); you may not use this file except in compliance
+ * * with the License. You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an
+ * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * * KIND, either express or implied. See the License for the
+ * * specific language governing permissions and limitations
+ * * under the License.
+ * *
+ *
+ */
+
+package org.apache.usergrid.persistence.index.query;
+
+
+/**
+ * A simple object that represents a field mapping.
+ *
+ * Examples:
+ * "select id", which will return id
+ *
+ * "select id:appfield" which will return id, but rename it appfield
+ */
+public class SelectFieldMapping {
+
+ private final String sourceFieldName;
+ private final String targetFieldName;
+
+
+ public SelectFieldMapping( final String sourceFieldName, final String targetFieldName ) {
+ this.sourceFieldName = sourceFieldName;
+ this.targetFieldName = targetFieldName;
+ }
+
+
+ public String getSourceFieldName() {
+ return sourceFieldName;
+ }
+
+
+ public String getTargetFieldName() {
+ return targetFieldName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2699dd30/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SortPredicate.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SortPredicate.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SortPredicate.java
new file mode 100644
index 0000000..70d0b30
--- /dev/null
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/SortPredicate.java
@@ -0,0 +1,126 @@
+/*
+ *
+ * *
+ * * Licensed to the Apache Software Foundation (ASF) under one
+ * * or more contributor license agreements. See the NOTICE file
+ * * distributed with this work for additional information
+ * * regarding copyright ownership. The ASF licenses this file
+ * * to you under the Apache License, Version 2.0 (the
+ * * "License"); you may not use this file except in compliance
+ * * with the License. You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an
+ * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * * KIND, either express or implied. See the License for the
+ * * specific language governing permissions and limitations
+ * * under the License.
+ * *
+ *
+ */
+
+package org.apache.usergrid.persistence.index.query;
+
+
+import java.io.Serializable;
+
+
+/**
+ * An object that represents a sort predicate
+ */
+public final class SortPredicate implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private final String propertyName;
+ private final SortDirection direction;
+
+
+ public SortPredicate( String propertyName, SortDirection direction ) {
+
+ if ( propertyName == null ) {
+ throw new NullPointerException( "Property name was null" );
+ }
+
+ if ( direction == null ) {
+ direction = SortDirection.ASCENDING;
+ }
+
+ this.propertyName = propertyName.trim();
+ this.direction = direction;
+ }
+
+
+ public SortPredicate( String propertyName, String direction ) {
+ this( propertyName, SortDirection.find( direction ) );
+ }
+
+
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+
+ public SortDirection getDirection() {
+ return direction;
+ }
+
+
+ @Override
+ public boolean equals( Object o ) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( ( o == null ) || ( super.getClass() != o.getClass() ) ) {
+ return false;
+ }
+
+ SortPredicate that = ( SortPredicate ) o;
+
+ if ( direction != that.direction ) {
+ return false;
+ }
+
+ return ( propertyName.equals( that.propertyName ) );
+ }
+
+
+ @Override
+ public int hashCode() {
+ int result = propertyName.hashCode();
+ result = ( 31 * result ) + direction.hashCode();
+ return result;
+ }
+
+
+ @Override
+ public String toString() {
+ return propertyName + ( ( direction == SortDirection.DESCENDING ) ? " DESC" : "" );
+ }
+
+
+ public enum SortDirection {
+ ASCENDING, DESCENDING;
+
+
+ public static SortDirection find( String s ) {
+ if ( s == null ) {
+ return ASCENDING;
+ }
+ s = s.toLowerCase();
+ if ( s.startsWith( "asc" ) ) {
+ return ASCENDING;
+ }
+ if ( s.startsWith( "des" ) ) {
+ return DESCENDING;
+ }
+ if ( s.equals( "+" ) ) {
+ return ASCENDING;
+ }
+ if ( s.equals( "-" ) ) {
+ return DESCENDING;
+ }
+ return ASCENDING;
+ }
+ }
+}