Commit ac0764be by Ashutosh Mestry Committed by Madhan Neethiraj

ATLAS-2229: DSL implementation using ANTLR #2

parent 728aac65
......@@ -392,8 +392,8 @@ public class SearchParameters implements Serializable {
GT(new String[]{">", "gt"}),
LTE(new String[]{"<=", "lte"}),
GTE(new String[]{">=", "gte"}),
EQ(new String[]{"eq", "="}),
NEQ(new String[]{"neq", "!="}),
EQ(new String[]{"=", "eq"}),
NEQ(new String[]{"!=", "neq"}),
IN(new String[]{"in", "IN"}),
LIKE(new String[]{"like", "LIKE"}),
STARTS_WITH(new String[]{"startsWith", "STARTSWITH", "begins_with", "BEGINS_WITH"}),
......
......@@ -685,7 +685,7 @@ public class EntityDiscoveryService implements AtlasDiscoveryService {
throw new AtlasBaseException(DISCOVERY_QUERY_FAILED, query);
}
QueryProcessor queryProcessor = new QueryProcessor(typeRegistry);
QueryProcessor queryProcessor = new QueryProcessor(typeRegistry, limit, offset);
Expression validExpression = queryProcessor.validate(expression);
GremlinQuery gremlinQuery = new GremlinTranslator(queryProcessor, validExpression).translate();
......@@ -928,13 +928,24 @@ public class EntityDiscoveryService implements AtlasDiscoveryService {
@Override
public String getDslQueryUsingTypeNameClassification(String query, String typeName, String classification) {
final String whereDSLKeyword = "where";
final String limitDSLKeyword = "limit";
final String whereFormat = whereDSLKeyword + " %s";
String queryStr = query == null ? "" : query;
if (org.apache.commons.lang3.StringUtils.isNoneEmpty(typeName)) {
if (StringUtils.isNotEmpty(typeName)) {
if(StringUtils.isNotEmpty(query)) {
String s = query.toLowerCase();
if(!s.startsWith(whereDSLKeyword) && !s.startsWith(limitDSLKeyword)) {
queryStr = String.format(whereFormat, query);
}
}
queryStr = escapeTypeName(typeName) + " " + queryStr;
}
if (org.apache.commons.lang3.StringUtils.isNoneEmpty(classification)) {
if (StringUtils.isNotEmpty(classification)) {
// isa works with a type name only - like hive_column isa PII; it doesn't work with more complex query
if (StringUtils.isEmpty(query)) {
queryStr += (" isa " + classification);
......
......@@ -21,8 +21,20 @@ package org.apache.atlas.query;
import org.apache.atlas.query.antlr4.AtlasDSLParser.*;
import org.apache.atlas.query.antlr4.AtlasDSLParserBaseVisitor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class DSLVisitor extends AtlasDSLParserBaseVisitor<String> {
private static final Logger LOG = LoggerFactory.getLogger(DSLVisitor.class);
private static final String AND = "AND";
private static final String OR = "OR";
private final QueryProcessor queryProcessor;
public DSLVisitor(QueryProcessor queryProcessor) {
......@@ -30,62 +42,50 @@ public class DSLVisitor extends AtlasDSLParserBaseVisitor<String> {
}
@Override
public String visitFromExpression(final FromExpressionContext ctx) {
FromSrcContext fromSrc = ctx.fromSrc();
AliasExprContext aliasExpr = fromSrc.aliasExpr();
if (aliasExpr != null) {
queryProcessor.addFromAlias(aliasExpr.identifier(0).getText(), aliasExpr.identifier(1).getText());
} else {
if (fromSrc.identifier() != null) {
queryProcessor.addFrom(fromSrc.identifier().getText());
} else {
queryProcessor.addFrom(fromSrc.literal().getText());
}
public String visitIsClause(IsClauseContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitIsClause({})", ctx);
}
return super.visitFromExpression(ctx);
queryProcessor.addFromIsA(ctx.arithE().getText(), ctx.identifier().getText());
return super.visitIsClause(ctx);
}
@Override
public String visitWhereClause(WhereClauseContext ctx) {
ExprContext expr = ctx.expr();
processExpr(expr.compE());
if (CollectionUtils.isNotEmpty(expr.exprRight())) {
for (ExprRightContext exprRight : expr.exprRight()) {
if (exprRight.K_AND() != null) {
// AND expression
processExpr(exprRight.compE());
}
// OR is tricky
}
}
return super.visitWhereClause(ctx);
public String visitHasClause(HasClauseContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitHasClause({})", ctx);
}
private void processExpr(final CompEContext compE) {
if (compE != null && compE.isClause() == null && compE.hasClause() == null && compE.isClause() == null) {
ComparisonClauseContext comparisonClause = compE.comparisonClause();
if(comparisonClause == null) {
comparisonClause = compE.arithE().multiE().atomE().expr().compE().comparisonClause();
queryProcessor.addFromProperty(ctx.arithE().getText(), ctx.identifier().getText());
return super.visitHasClause(ctx);
}
if (comparisonClause != null) {
String lhs = comparisonClause.arithE(0).getText();
String op = comparisonClause.operator().getText().toUpperCase();
String rhs = comparisonClause.arithE(1).getText();
queryProcessor.addWhere(lhs, op, rhs);
}
@Override
public String visitLimitOffset(LimitOffsetContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitLimitOffset({})", ctx);
}
queryProcessor.addLimit(ctx.limitClause().NUMBER().toString(),
(ctx.offsetClause() == null ? "0" : ctx.offsetClause().NUMBER().getText()));
return super.visitLimitOffset(ctx);
}
@Override
public String visitSelectExpr(SelectExprContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitSelectExpr({})", ctx);
}
if (!(ctx.getParent() instanceof GroupByExpressionContext)) {
String[] items = new String[ctx.selectExpression().size()];
List<Pair<String, String>> items = new ArrayList<>();
for (int i = 0; i < ctx.selectExpression().size(); i++) {
items[i] = ctx.selectExpression(i).expr().getText();
String idf = ctx.selectExpression(i).expr().getText();
String alias = (ctx.selectExpression(i).K_AS() != null) ?
ctx.selectExpression(i).identifier().getText() : "";
items.add(new MutablePair<String, String>(idf, alias));
}
queryProcessor.addSelect(items);
......@@ -94,34 +94,140 @@ public class DSLVisitor extends AtlasDSLParserBaseVisitor<String> {
}
@Override
public String visitLimitOffset(LimitOffsetContext ctx) {
queryProcessor.addLimit(ctx.limitClause().NUMBER().toString(),
(ctx.offsetClause() == null ? "0" : ctx.offsetClause().NUMBER().getText()));
return super.visitLimitOffset(ctx);
public String visitOrderByExpr(OrderByExprContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitOrderByExpr({})", ctx);
}
@Override
public String visitOrderByExpr(OrderByExprContext ctx) {
queryProcessor.addOrderBy(ctx.expr().getText(), (ctx.sortOrder() != null && ctx.sortOrder().getText().equalsIgnoreCase("desc")));
return super.visitOrderByExpr(ctx);
}
@Override
public String visitIsClause(IsClauseContext ctx) {
queryProcessor.addFromIsA(ctx.arithE().getText(), ctx.identifier().getText());
return super.visitIsClause(ctx);
public String visitWhereClause(WhereClauseContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitWhereClause({})", ctx);
}
// The first expr shouldn't be processed if there are following exprs
ExprContext expr = ctx.expr();
processExpr(expr, queryProcessor);
return super.visitWhereClause(ctx);
}
@Override
public String visitHasClause(HasClauseContext ctx) {
queryProcessor.addFromProperty(ctx.arithE().getText(), ctx.identifier().getText());
return super.visitHasClause(ctx);
public String visitFromExpression(final FromExpressionContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitFromExpression({})", ctx);
}
FromSrcContext fromSrc = ctx.fromSrc();
AliasExprContext aliasExpr = fromSrc.aliasExpr();
if (aliasExpr != null) {
queryProcessor.addFromAlias(aliasExpr.identifier(0).getText(), aliasExpr.identifier(1).getText());
} else {
if (fromSrc.identifier() != null) {
queryProcessor.addFrom(fromSrc.identifier().getText());
} else {
queryProcessor.addFrom(fromSrc.literal().getText());
}
}
return super.visitFromExpression(ctx);
}
@Override
public String visitGroupByExpression(GroupByExpressionContext ctx) {
if (LOG.isDebugEnabled()) {
LOG.debug("=> DSLVisitor.visitGroupByExpression({})", ctx);
}
String s = ctx.selectExpr().getText();
queryProcessor.addGroupBy(s);
return super.visitGroupByExpression(ctx);
}
private void processExpr(final ExprContext expr, QueryProcessor queryProcessor) {
if (CollectionUtils.isNotEmpty(expr.exprRight())) {
processExprRight(expr, queryProcessor);
} else {
processExpr(expr.compE(), queryProcessor);
}
}
private void processExprRight(final ExprContext expr, QueryProcessor queryProcessor) {
QueryProcessor nestedProcessor = queryProcessor.createNestedProcessor();
List<String> nestedQueries = new ArrayList<>();
String prev = null;
// Process first expression then proceed with the others
// expr -> compE exprRight*
processExpr(expr.compE(), nestedProcessor);
nestedQueries.add(nestedProcessor.getText());
for (ExprRightContext exprRight : expr.exprRight()) {
nestedProcessor = queryProcessor.createNestedProcessor();
// AND expression
if (exprRight.K_AND() != null) {
if (prev == null) prev = AND;
if (OR.equalsIgnoreCase(prev)) {
// Change of context
QueryProcessor orClause = nestedProcessor.createNestedProcessor();
orClause.addOrClauses(nestedQueries);
nestedQueries.clear();
nestedQueries.add(orClause.getText());
}
prev = AND;
}
// OR expression
if (exprRight.K_OR() != null) {
if (prev == null) prev = OR;
if (AND.equalsIgnoreCase(prev)) {
// Change of context
QueryProcessor andClause = nestedProcessor.createNestedProcessor();
andClause.addAndClauses(nestedQueries);
nestedQueries.clear();
nestedQueries.add(andClause.getText());
}
prev = OR;
}
processExpr(exprRight.compE(), nestedProcessor);
nestedQueries.add(nestedProcessor.getText());
}
if (AND.equalsIgnoreCase(prev)) {
queryProcessor.addAndClauses(nestedQueries);
}
if (OR.equalsIgnoreCase(prev)) {
queryProcessor.addOrClauses(nestedQueries);
}
}
private void processExpr(final CompEContext compE, final QueryProcessor queryProcessor) {
if (compE != null && compE.isClause() == null && compE.hasClause() == null && compE.isClause() == null) {
ComparisonClauseContext comparisonClause = compE.comparisonClause();
// The nested expression might have ANDs/ORs
if(comparisonClause == null) {
ExprContext exprContext = compE.arithE().multiE().atomE().expr();
// Only extract comparison clause if there are no nested exprRight clauses
if (CollectionUtils.isEmpty(exprContext.exprRight())) {
comparisonClause = exprContext.compE().comparisonClause();
}
}
if (comparisonClause != null) {
String lhs = comparisonClause.arithE(0).getText();
String op = comparisonClause.operator().getText().toUpperCase();
String rhs = comparisonClause.arithE(1).getText();
queryProcessor.addWhere(lhs, op, rhs);
} else {
processExpr(compE.arithE().multiE().atomE().expr(), queryProcessor);
}
}
}
}
/**
* 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.atlas.query;
import org.apache.commons.lang.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class IdentifierHelper {
public static String stripQuotes(String quotedIdentifier) {
String ret = quotedIdentifier;
if (isQuoted(quotedIdentifier)) {
ret = quotedIdentifier.substring(1, quotedIdentifier.length() - 1);
}
return ret;
}
public static Advice create(QueryProcessor.Context context,
org.apache.atlas.query.Lookup lookup,
String identifier) {
Advice ia = new Advice(identifier);
ia.update(lookup, context);
return ia;
}
private static String extract(Pattern p, String s) {
Matcher m = p.matcher(s);
return m.find() ? m.group(1) : s;
}
public static String getQualifiedName(org.apache.atlas.query.Lookup lookup,
QueryProcessor.Context context,
String name) {
return lookup.getQualifiedName(context, name);
}
public static boolean isQuoted(String val) {
boolean ret = false;
if (val != null && val.length() > 1) {
char first = val.charAt(0);
char last = val.charAt(val.length() - 1);
if (first == last && (first == '\'' || first == '"' || first == '`')) {
ret = true;
}
}
return ret;
}
public static String removeQuotes(String rhs) {
return rhs.replace("\"", "").replace("'", "");
}
public static String getQuoted(String s) {
return String.format("'%s'", s);
}
public static class Advice {
private String raw;
private String actual;
private String[] parts;
private String typeName;
private String attributeName;
private boolean isPrimitive;
private String edgeLabel;
private String edgeDirection;
private boolean introduceType;
private boolean hasSubtypes;
private String subTypes;
private boolean isTrait;
private boolean newContext;
private boolean isAttribute;
private String qualifiedName;
private boolean isDate;
public Advice(String s) {
this.raw = removeQuotes(s);
this.actual = IdentifierHelper.stripQuotes(raw);
}
private void update(org.apache.atlas.query.Lookup lookup, QueryProcessor.Context context) {
newContext = context.isEmpty();
if(!newContext) {
if(context.aliasMap.containsKey(this.raw)) {
raw = context.aliasMap.get(this.raw);
}
updateParts();
updateTypeInfo(lookup, context);
isTrait = lookup.isTraitType(context);
updateEdgeInfo(lookup, context);
introduceType = !context.hasAlias(parts[0]);
updateSubTypes(lookup, context);
}
}
private void updateSubTypes(org.apache.atlas.query.Lookup lookup, QueryProcessor.Context context) {
if(isTrait) {
return;
}
hasSubtypes = lookup.doesTypeHaveSubTypes(context);
if(hasSubtypes) {
subTypes = lookup.getTypeAndSubTypes(context);
}
}
private void updateEdgeInfo(org.apache.atlas.query.Lookup lookup, QueryProcessor.Context context) {
if(isPrimitive == false && isTrait == false) {
edgeLabel = lookup.getRelationshipEdgeLabel(context, attributeName);
edgeDirection = "OUT";
typeName = lookup.getTypeFromEdge(context, attributeName);
}
}
private void updateTypeInfo(org.apache.atlas.query.Lookup lookup, QueryProcessor.Context context) {
if(parts.length == 1) {
typeName = context.getActiveTypeName();
attributeName = parts[0];
isAttribute = lookup.hasAttribute(context, typeName);
qualifiedName = lookup.getQualifiedName(context, attributeName);
isPrimitive = lookup.isPrimitive(context, attributeName);
setIsDate(lookup, context);
}
if(parts.length == 2) {
if(context.hasAlias(parts[0])) {
typeName = context.getTypeNameFromAlias(parts[0]);
attributeName = parts[1];
isPrimitive = lookup.isPrimitive(context, attributeName);
setIsDate(lookup, context);
}
else {
isAttribute = lookup.hasAttribute(context, parts[0]);
if(isAttribute) {
attributeName = parts[0];
isPrimitive = lookup.isPrimitive(context, attributeName);
setIsDate(lookup, context);
} else {
typeName = parts[0];
attributeName = parts[1];
isPrimitive = lookup.isPrimitive(context, attributeName);
setIsDate(lookup, context);
}
}
qualifiedName = lookup.getQualifiedName(context, attributeName);
}
}
private void setIsDate(Lookup lookup, QueryProcessor.Context context) {
if(isPrimitive) {
isDate = lookup.isDate(context, attributeName);
}
}
private void updateParts() {
parts = StringUtils.split(raw, ".");
}
public String getQualifiedName() {
return qualifiedName;
}
public boolean isPrimitive() {
return isPrimitive;
}
public String getEdgeLabel() {
return edgeLabel;
}
public String getTypeName() {
return typeName;
}
public boolean getIntroduceType() {
return introduceType;
}
public boolean isTrait() {
return isTrait;
}
public boolean hasSubtypes() {
return hasSubtypes;
}
public String getSubTypes() {
return subTypes;
}
public String get() {
return actual;
}
public boolean isNewContext() {
return newContext;
}
public boolean isDate() {
return isDate;
}
}
}
/**
* 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.atlas.query;
import org.apache.atlas.type.AtlasType;
public interface Lookup {
AtlasType getType(String typeName);
String getQualifiedName(QueryProcessor.Context context, String name);
boolean isPrimitive(QueryProcessor.Context context, String attributeName);
String getRelationshipEdgeLabel(QueryProcessor.Context context, String attributeName);
boolean hasAttribute(QueryProcessor.Context context, String typeName);
boolean doesTypeHaveSubTypes(QueryProcessor.Context context);
String getTypeAndSubTypes(QueryProcessor.Context context);
boolean isTraitType(QueryProcessor.Context context);
String getTypeFromEdge(QueryProcessor.Context context, String item);
boolean isDate(QueryProcessor.Context context, String attributeName);
}
......@@ -22,13 +22,10 @@ import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.discovery.SearchParameters;
import org.apache.atlas.query.Expressions.Expression;
import org.apache.atlas.type.AtlasArrayType;
import org.apache.atlas.type.AtlasBuiltInTypes;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.*;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -38,167 +35,196 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class QueryProcessor {
private static final Logger LOG = LoggerFactory.getLogger(QueryProcessor.class);
private final int DEFAULT_QUERY_RESULT_LIMIT = 25;
private final int DEFAULT_QUERY_RESULT_OFFSET = 0;
private final Pattern SINGLE_QUOTED_IDENTIFIER = Pattern.compile("'(\\w[\\w\\d\\.\\s]*)'");
private final Pattern DOUBLE_QUOTED_IDENTIFIER = Pattern.compile("\"(\\w[\\w\\d\\.\\s]*)\"");
private final Pattern BACKTICK_QUOTED_IDENTIFIER = Pattern.compile("`(\\w[\\w\\d\\.\\s]*)`");
private final boolean isNestedQuery;
private final List<String> errorList = new ArrayList<>();
private final GremlinClauseList queryClauses = new GremlinClauseList(errorList);
private final GremlinClauseList queryClauses = new GremlinClauseList();
private int providedLimit = DEFAULT_QUERY_RESULT_LIMIT;
private int providedOffset = DEFAULT_QUERY_RESULT_OFFSET;
private int currentStep;
private final TypeRegistryLookup registryLookup;
private final org.apache.atlas.query.Lookup lookup;
private Context context;
@Inject
public QueryProcessor(AtlasTypeRegistry typeRegistry) {
registryLookup = new TypeRegistryLookup(errorList, typeRegistry);
this.isNestedQuery = false;
lookup = new Lookup(errorList, typeRegistry);
context = new Context(errorList, lookup);
init();
}
public QueryProcessor(AtlasTypeRegistry typeRegistry, int limit, int offset) {
this(typeRegistry);
this.providedLimit = limit;
this.providedOffset = offset < 0 ? DEFAULT_QUERY_RESULT_OFFSET : offset;
}
@VisibleForTesting
public QueryProcessor(TypeRegistryLookup lookup) {
registryLookup = lookup;
QueryProcessor(org.apache.atlas.query.Lookup lookup, Context context) {
this.isNestedQuery = false;
this.lookup = lookup;
this.context = context;
init();
}
private void init() {
add(GremlinClause.G);
add(GremlinClause.V);
public QueryProcessor(org.apache.atlas.query.Lookup registryLookup, boolean isNestedQuery) {
this.isNestedQuery = isNestedQuery;
this.lookup = registryLookup;
init();
}
public Expression validate(Expression expression) {
return expression.isReady();
}
private void init() {
if (!isNestedQuery) {
add(GremlinClause.G);
add(GremlinClause.V);
} else {
add(GremlinClause.NESTED_START);
}
}
public void addFrom(String typeName) {
if (LOG.isDebugEnabled()) {
LOG.debug("addFrom(typeName={})", typeName);
}
String actualTypeName = extractIdentifier(typeName);
IdentifierHelper.Advice ta = getAdvice(typeName);
if(context.shouldRegister(ta.get())) {
context.registerActive(ta.get());
if(registryLookup.isTypeTrait(actualTypeName)) {
addTraitAndRegister(actualTypeName);
} else if (!registryLookup.hasActiveType()) {
registryLookup.registerActive(actualTypeName);
if(registryLookup.doesActiveTypeHaveSubTypes()) {
add(GremlinClause.HAS_TYPE_WITHIN, registryLookup.getActiveTypeAndSubTypes());
IdentifierHelper.Advice ia = getAdvice(ta.get());
if (ia.isTrait()) {
add(GremlinClause.TRAIT, ia.get());
} else {
if (ia.hasSubtypes()) {
add(GremlinClause.HAS_TYPE_WITHIN, ia.getSubTypes());
} else {
add(GremlinClause.HAS_TYPE, actualTypeName);
add(GremlinClause.HAS_TYPE, ia.get());
}
}
} else {
add(GremlinClause.OUT, registryLookup.getRelationshipEdgeLabelForActiveType(actualTypeName));
registryLookup.registerActive(registryLookup.getTypeFromEdge(actualTypeName));
IdentifierHelper.Advice ia = getAdvice(ta.get());
introduceType(ia);
}
}
private void addTraitAndRegister(String typeName) {
if (LOG.isDebugEnabled()) {
LOG.debug("addTraitAndRegister(typeName={})", typeName);
private void introduceType(IdentifierHelper.Advice ia) {
if (!ia.isPrimitive() && ia.getIntroduceType()) {
add(GremlinClause.OUT, ia.getEdgeLabel());
context.registerActive(ia.getTypeName());
}
}
add(GremlinClause.TRAIT, typeName);
registryLookup.registerActive(typeName);
private IdentifierHelper.Advice getAdvice(String actualTypeName) {
return IdentifierHelper.create(context, lookup, actualTypeName);
}
public void addFromIsA(String typeName, String trait) {
public void addFromProperty(String typeName, String attribute) {
if (LOG.isDebugEnabled()) {
LOG.debug("addFromIsA(typeName={}, trait={})", typeName, trait);
LOG.debug("addFromProperty(typeName={}, attribute={})", typeName, attribute);
}
if(!registryLookup.hasActiveType()) {
addFrom(typeName);
add(GremlinClause.HAS_PROPERTY,
IdentifierHelper.getQualifiedName(lookup, context, attribute));
}
add(GremlinClause.TRAIT, trait);
public void addFromIsA(String typeName, String traitName) {
addFrom(typeName);
add(GremlinClause.TRAIT, traitName);
}
public void addFromProperty(String typeName, String attribute) {
public void addWhere(String lhs, String operator, String rhs) {
if (LOG.isDebugEnabled()) {
LOG.debug("addFromIsA(typeName={}, attribute={})", typeName, attribute);
LOG.debug("addWhere(lhs={}, operator={}, rhs={})", lhs, operator, rhs);
}
if(registryLookup.isSameAsActive(typeName) == false) {
addFrom(typeName);
String currentType = context.getActiveTypeName();
SearchParameters.Operator op = SearchParameters.Operator.fromString(operator);
IdentifierHelper.Advice org = null;
IdentifierHelper.Advice lhsI = getAdvice(lhs);
if(lhsI.isPrimitive() == false) {
introduceType(lhsI);
org = lhsI;
lhsI = getAdvice(lhs);
}
add(GremlinClause.HAS_PROPERTY, registryLookup.getQualifiedAttributeName(attribute));
if(lhsI.isDate()) {
rhs = parseDate(rhs);
}
public void addFromAlias(String typeName, String alias) {
if (LOG.isDebugEnabled()) {
LOG.debug("addFromAlias(typeName={}, alias={})", typeName, alias);
rhs = addQuotesIfNecessary(rhs);
if(op == SearchParameters.Operator.LIKE) {
add(GremlinClause.TEXT_CONTAINS, lhsI.getQualifiedName(), rhs.replace("*", ".*").replace('?', '.'));
} else if(op == SearchParameters.Operator.IN) {
add(GremlinClause.HAS_OPERATOR, lhsI.getQualifiedName(), "within", rhs);
} else {
add(GremlinClause.HAS_OPERATOR, lhsI.getQualifiedName(), op.getSymbols()[1], rhs);
}
addFrom(typeName);
addAsClause(alias);
if(org != null && org.isPrimitive() == false && org.getIntroduceType()) {
add(GremlinClause.IN, org.getEdgeLabel());
context.registerActive(currentType);
}
}
public void addWhere(String lhs, String operator, String rhs) {
if (LOG.isDebugEnabled()) {
LOG.debug("addWhere(lhs={}, operator={}, rhs={})", lhs, operator, rhs);
private String addQuotesIfNecessary(String rhs) {
if(IdentifierHelper.isQuoted(rhs)) return rhs;
return quoted(rhs);
}
lhs = registryLookup.getQualifiedAttributeName(lhs);
private static String quoted(String rhs) {
return IdentifierHelper.getQuoted(rhs);
}
SearchParameters.Operator op = SearchParameters.Operator.fromString(operator);
switch (op) {
case LT:
add(GremlinClause.HAS_OPERATOR, lhs, "lt", rhs);
break;
case GT:
add(GremlinClause.HAS_OPERATOR, lhs, "gt", rhs);
break;
case LTE:
add(GremlinClause.HAS_OPERATOR, lhs, "lte", rhs);
break;
case GTE:
add(GremlinClause.HAS_OPERATOR, lhs, "gte", rhs);
break;
case EQ:
add(GremlinClause.HAS_OPERATOR, lhs, "eq", rhs);
break;
case NEQ:
add(GremlinClause.HAS_OPERATOR, lhs, "neq", rhs);
break;
case IN:
// TODO: Handle multiple RHS values
add(GremlinClause.HAS_OPERATOR, lhs, "within", rhs);
break;
case LIKE:
add(GremlinClause.TEXT_CONTAINS, lhs, rhs.replace("*", ".*").replace('?', '.'));
break;
}
}
public void addSelect(String[] items) {
if (LOG.isDebugEnabled()) {
LOG.debug("addSelect(items.length={})", items != null ? items.length : -1);
private String parseDate(String rhs) {
String s = IdentifierHelper.isQuoted(rhs) ?
IdentifierHelper.removeQuotes(rhs) :
rhs;
return String.format("'%d'", DateTime.parse(s).getMillis());
}
StringBuilder sb = new StringBuilder();
public void addAndClauses(List<String> clauses) {
queryClauses.add(GremlinClause.AND, StringUtils.join(clauses, ','));
}
for (int i = 0; i < items.length; i++) {
String s = registryLookup.getQualifiedAttributeName(items[i]);
public void addOrClauses(List<String> clauses) {
queryClauses.add(GremlinClause.OR, StringUtils.join(clauses, ','));
}
if (items[i].contains(".") || registryLookup.isAttributePrimitiveTypeForActiveType(items[i])) {
sb.append(String.format("'%s'", s));
public void addSelect(List<Pair<String, String>> items) {
if (LOG.isDebugEnabled()) {
LOG.debug("addSelect(items.length={})", items != null ? items.size() : -1);
}
if (i != items.length - 1) {
sb.append(", ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
IdentifierHelper.Advice ia = getAdvice(items.get(i).getLeft());
if(StringUtils.isNotEmpty(items.get(i).getRight())) {
context.aliasMap.put(items.get(i).getRight(), ia.getQualifiedName());
}
} else {
add(GremlinClause.OUT, registryLookup.getRelationshipEdgeLabelForActiveType(items[i]));
if(!ia.isPrimitive() && ia.getIntroduceType()) {
add(GremlinClause.OUT, ia.getEdgeLabel());
add(GremlinClause.AS, getCurrentStep());
addSelectClause(getCurrentStep());
incrementCurrentStep();
} else {
sb.append(quoted(ia.getQualifiedName()));
}
if (i != items.size() - 1) {
sb.append(",");
}
}
......@@ -207,144 +233,156 @@ public class QueryProcessor {
}
}
public void addLimit(String limit, String offset) {
private void addSelectClause(String s) {
if (LOG.isDebugEnabled()) {
LOG.debug("addLimit(limit={}, offset={})", limit, offset);
LOG.debug("addSelectClause(s={})", s);
}
add(GremlinClause.ORDER);
if (offset.equalsIgnoreCase("0")) {
add(GremlinClause.LIMIT, limit);
} else {
addRangeClause(offset, limit);
add(GremlinClause.SELECT, s);
}
private String getCurrentStep() {
return String.format("s%d", currentStep);
}
public void addGroupBy(String item) {
if (LOG.isDebugEnabled()) {
LOG.debug("addGroupBy(item={})", item);
private void incrementCurrentStep() {
currentStep++;
}
add(GremlinClause.GROUP);
addByClause(item, false);
public QueryProcessor createNestedProcessor() {
QueryProcessor qp = new QueryProcessor(lookup, true);
qp.context = this.context;
return qp;
}
private void addRangeClause(String startIndex, String endIndex) {
private void addValueMapClause(String s) {
if (LOG.isDebugEnabled()) {
LOG.debug("addRangeClause(startIndex={}, endIndex={})", startIndex, endIndex);
LOG.debug("addValueMapClause(s={})", s);
}
add(GremlinClause.RANGE, startIndex, startIndex, endIndex);
add(GremlinClause.VALUE_MAP, s);
}
public String getText() {
String[] items = new String[queryClauses.size()];
for (int i = 0; i < queryClauses.size(); i++) {
items[i] = queryClauses.getValue(i);
public void addFromAlias(String typeName, String alias) {
if (LOG.isDebugEnabled()) {
LOG.debug("addFromAlias(typeName={}, alias={})", typeName, alias);
}
String ret = StringUtils.join(items, ".");
addFrom(typeName);
addAsClause(alias);
context.registerAlias(alias);
}
public void addAsClause(String stepName) {
if (LOG.isDebugEnabled()) {
LOG.debug("getText() => {}", ret);
LOG.debug("addAsClause(stepName={})", stepName);
}
return ret;
add(GremlinClause.AS, stepName);
}
public void close() {
if(queryClauses.hasClause(GremlinClause.LIMIT) == -1) {
add(GremlinClause.LIMIT, "" + DEFAULT_QUERY_RESULT_LIMIT);
private void add(GremlinClause clause, String... args) {
queryClauses.add(new GremlinClauseValue(clause, clause.get(args)));
}
add(GremlinClause.TO_LIST);
private void addRangeClause(String startIndex, String endIndex) {
if (LOG.isDebugEnabled()) {
LOG.debug("addRangeClause(startIndex={}, endIndex={})", startIndex, endIndex);
}
public boolean hasSelect() {
return (queryClauses.hasClause(GremlinClause.VALUE_MAP) != -1);
add(GremlinClause.RANGE, startIndex, startIndex, endIndex);
}
public void addAsClause(String stepName) {
public void addGroupBy(String item) {
if (LOG.isDebugEnabled()) {
LOG.debug("addAsClause(stepName={})", stepName);
LOG.debug("addGroupBy(item={})", item);
}
add(GremlinClause.AS, stepName);
registryLookup.registerStepType(stepName);
add(GremlinClause.GROUP);
addByClause(item, false);
}
public void addOrderBy(String name, boolean isDesc) {
private void addByClause(String name, boolean descr) {
if (LOG.isDebugEnabled()) {
LOG.debug("addOrderBy(name={}, isDesc={})", name, isDesc);
LOG.debug("addByClause(name={})", name, descr);
}
add(GremlinClause.ORDER);
addByClause(registryLookup.getQualifiedAttributeName(name), isDesc);
IdentifierHelper.Advice ia = getAdvice(name);
add((!descr) ? GremlinClause.BY : GremlinClause.BY_DESC,
ia.getQualifiedName());
}
private void addValueMapClause(String s) {
public void addLimit(String limit, String offset) {
if (LOG.isDebugEnabled()) {
LOG.debug("addValueMapClause(s={})", s);
LOG.debug("addLimit(limit={}, offset={})", limit, offset);
}
add(GremlinClause.VALUE_MAP, s);
if (offset.equalsIgnoreCase("0")) {
add(GremlinClause.LIMIT, limit);
} else {
addRangeClause(offset, limit);
}
}
private void addSelectClause(String s) {
if (LOG.isDebugEnabled()) {
LOG.debug("addSelectClause(s={})", s);
public void close() {
if (queryClauses.isEmpty()) {
queryClauses.clear();
return;
}
add(GremlinClause.SELECT, s);
if (queryClauses.hasClause(GremlinClause.LIMIT) == -1) {
addLimit(Integer.toString(providedLimit), Integer.toString(providedOffset));
}
private void addByClause(String name, boolean descr) {
if (LOG.isDebugEnabled()) {
LOG.debug("addByClause(name={})", name, descr);
add(GremlinClause.TO_LIST);
}
add((!descr) ? GremlinClause.BY : GremlinClause.BY_DESC,
registryLookup.getQualifiedAttributeName(name));
public String getText() {
String[] items = new String[queryClauses.size()];
for (int i = 0; i < queryClauses.size(); i++) {
items[i] = queryClauses.getValue(i);
}
private String getCurrentStep() {
return String.format("s%d", currentStep);
String ret = StringUtils.join(items, ".");
if (LOG.isDebugEnabled()) {
LOG.debug("getText() => {}", ret);
}
private void incrementCurrentStep() {
currentStep++;
return ret;
}
private void add(GremlinClause clause, String... args) {
queryClauses.add(new GremlinClauseValue(clause, clause.get(args)));
public boolean hasSelect() {
return (queryClauses.hasClause(GremlinClause.VALUE_MAP) != -1);
}
private String extractIdentifier(String quotedIdentifier) {
String ret;
public void addOrderBy(String name, boolean isDesc) {
if (LOG.isDebugEnabled()) {
LOG.debug("addOrderBy(name={}, isDesc={})", name, isDesc);
}
if (quotedIdentifier.charAt(0) == '`') {
ret = extract(BACKTICK_QUOTED_IDENTIFIER, quotedIdentifier);
} else if (quotedIdentifier.charAt(0) == '\'') {
ret = extract(SINGLE_QUOTED_IDENTIFIER, quotedIdentifier);
} else if (quotedIdentifier.charAt(0) == '"') {
ret = extract(DOUBLE_QUOTED_IDENTIFIER, quotedIdentifier);
} else {
ret = quotedIdentifier;
add(GremlinClause.ORDER);
addByClause(name, isDesc);
updateSelectClausePosition();
}
return ret;
private void updateSelectClausePosition() {
int selectClauseIndex = queryClauses.hasClause(GremlinClause.VALUE_MAP);
if(-1 == selectClauseIndex) {
return;
}
private String extract(Pattern p, String s) {
Matcher m = p.matcher(s);
return m.find() ? m.group(1) : s;
GremlinClauseValue gcv = queryClauses.remove(selectClauseIndex);
queryClauses.add(gcv);
}
private enum GremlinClause {
AS("as('%s')"),
BY("by('%s')"),
BY_DESC("by('%s', decr)"),
DEDUP("dedup()"),
G("g"),
GROUP("group()"),
HAS("has('%s', %s)"),
......@@ -354,7 +392,11 @@ public class QueryProcessor {
HAS_TYPE("has('__typeName', '%s')"),
HAS_TYPE_WITHIN("has('__typeName', within(%s))"),
HAS_WITHIN("has('%s', within(%s))"),
IN("in()"),
IN("in('%s')"),
OR("or(%s)"),
AND("and(%s)"),
NESTED_START("__"),
NESTED_HAS_OPERATOR("has('%s', %s(%s))"),
LIMIT("limit(%s)"),
ORDER("order()"),
OUT("out('%s')"),
......@@ -400,13 +442,9 @@ public class QueryProcessor {
}
private static class GremlinClauseList {
private final List<String> errorList;
private AtlasEntityType activeType;
private final List<GremlinClauseValue> list;
private GremlinClauseList(List<String> errorList) {
this.errorList = errorList;
private GremlinClauseList() {
this.list = new LinkedList<>();
}
......@@ -416,7 +454,6 @@ public class QueryProcessor {
public void add(GremlinClauseValue g, AtlasEntityType t) {
add(g);
activeType = t;
}
public void add(GremlinClause clause, String... args) {
......@@ -427,6 +464,10 @@ public class QueryProcessor {
return list.get(i).value;
}
public GremlinClauseValue get(int i) {
return list.get(i);
}
public int size() {
return list.size();
}
......@@ -439,133 +480,218 @@ public class QueryProcessor {
return -1;
}
public boolean isEmpty() {
return list.size() == 0 || list.size() == 2;
}
public void clear() {
list.clear();
}
public GremlinClauseValue remove(int index) {
GremlinClauseValue gcv = get(index);
list.remove(index);
return gcv;
}
}
@VisibleForTesting
static class TypeRegistryLookup {
static class Context {
private final List<String> errorList;
private final AtlasTypeRegistry typeRegistry;
private AtlasEntityType activeType;
private final Map<String, AtlasEntityType> asClauseContext = new HashMap<>();
org.apache.atlas.query.Lookup lookup;
private AtlasType activeType;
Map<String, String> aliasMap = new HashMap<>();
public TypeRegistryLookup(List<String> errorList, AtlasTypeRegistry typeRegistry) {
public Context(List<String> errorList, org.apache.atlas.query.Lookup lookup) {
this.lookup = lookup;
this.errorList = errorList;
this.typeRegistry = typeRegistry;
}
public void registerActive(String typeName) {
activeType = typeRegistry.getEntityTypeByName(typeName);
if(shouldRegister(typeName)) {
activeType = lookup.getType(typeName);
}
public boolean hasActiveType() {
return (activeType != null);
aliasMap.put(typeName, typeName);
}
public void registerStepType(String stepName) {
if (!asClauseContext.containsKey(stepName)) {
asClauseContext.put(stepName, activeType);
} else {
addError(String.format("Multiple steps with same name detected: %s", stepName));
public AtlasType getActiveType() {
return activeType;
}
public AtlasEntityType getActiveEntityType() {
return (activeType instanceof AtlasEntityType) ?
(AtlasEntityType) activeType :
null;
}
protected void addError(String s) {
errorList.add(s);
public String getActiveTypeName() {
return activeType.getTypeName();
}
public boolean shouldRegister(String typeName) {
return activeType == null ||
(activeType != null && !StringUtils.equals(getActiveTypeName(), typeName)) &&
(activeType != null && !lookup.hasAttribute(this, typeName));
}
public void registerAlias(String alias) {
if(aliasMap.containsKey(alias)) {
errorList.add(String.format("Duplicate alias found: %s for type %s already present.", alias, getActiveEntityType()));
return;
}
aliasMap.put(alias, getActiveTypeName());
}
public boolean hasAlias(String alias) {
return aliasMap.containsKey(alias);
}
public String getTypeNameFromAlias(String alias) {
return aliasMap.get(alias);
}
public boolean isEmpty() {
return activeType == null;
}
}
private static class Lookup implements org.apache.atlas.query.Lookup {
private final List<String> errorList;
private final AtlasTypeRegistry typeRegistry;
public Lookup(List<String> errorList, AtlasTypeRegistry typeRegistry) {
this.errorList = errorList;
this.typeRegistry = typeRegistry;
}
@Override
public AtlasType getType(String typeName) {
try {
return typeRegistry.getType(typeName);
} catch (AtlasBaseException e) {
addError(e.getMessage());
}
public String getRelationshipEdgeLabelForActiveType(String item) {
return getRelationshipEdgeLabel(activeType, item);
return null;
}
private String getRelationshipEdgeLabel(AtlasEntityType t, String item) {
if(t == null) {
@Override
public String getQualifiedName(Context context, String name) {
try {
AtlasEntityType et = context.getActiveEntityType();
if(et == null) {
return "";
}
AtlasStructType.AtlasAttribute attr = t.getAttribute(item);
return (attr != null) ? attr.getRelationshipEdgeLabel() : "";
return et.getQualifiedAttributeName(name);
} catch (AtlasBaseException e) {
addError(e.getMessage());
}
protected boolean isAttributePrimitiveTypeForActiveType(String name) {
return isAttributePrimitiveType(activeType, name);
return "";
}
private boolean isAttributePrimitiveType(AtlasEntityType t, String name) {
if (activeType == null) {
protected void addError(String s) {
errorList.add(s);
}
@Override
public boolean isPrimitive(Context context, String attributeName) {
AtlasEntityType et = context.getActiveEntityType();
if(et == null) {
return false;
}
AtlasType attrType = t.getAttributeType(name);
TypeCategory attrTypeCategory = attrType.getTypeCategory();
AtlasType attr = et.getAttributeType(attributeName);
if(attr == null) {
return false;
}
return (attrTypeCategory == TypeCategory.PRIMITIVE || attrTypeCategory == TypeCategory.ENUM);
TypeCategory attrTypeCategory = attr.getTypeCategory();
return (attrTypeCategory != null) && (attrTypeCategory == TypeCategory.PRIMITIVE || attrTypeCategory == TypeCategory.ENUM);
}
public boolean isTypeTrait(String name) {
return (typeRegistry.getClassificationTypeByName(name) != null);
@Override
public String getRelationshipEdgeLabel(Context context, String attributeName) {
AtlasEntityType et = context.getActiveEntityType();
if(et == null) {
return "";
}
public String getQualifiedAttributeName(String item) {
if (item.contains(".")) {
String[] keyValue = StringUtils.split(item, ".");
AtlasStructType.AtlasAttribute attr = et.getAttribute(attributeName);
return (attr != null) ? attr.getRelationshipEdgeLabel() : "";
}
if (!asClauseContext.containsKey(keyValue[0])) {
return item;
} else {
String s = getStitchedString(keyValue, 1, keyValue.length - 1);
return getQualifiedAttributeNameFromType(
asClauseContext.get(keyValue[0]), s);
@Override
public boolean hasAttribute(Context context, String typeName) {
return (context.getActiveEntityType() != null) && context.getActiveEntityType().getAttribute(typeName) != null;
}
@Override
public boolean doesTypeHaveSubTypes(Context context) {
return (context.getActiveEntityType() != null && context.getActiveEntityType().getAllSubTypes().size() > 0);
}
return getQualifiedAttributeNameFromType(activeType, item);
@Override
public String getTypeAndSubTypes(Context context) {
String[] str = context.getActiveEntityType() != null ?
context.getActiveEntityType().getTypeAndAllSubTypes().toArray(new String[]{}) :
new String[]{};
if(str.length == 0) {
return null;
}
protected String getStitchedString(String[] keyValue, int startIndex, int endIndex) {
if(startIndex == endIndex) {
return keyValue[startIndex];
String[] quoted = new String[str.length];
for (int i = 0; i < str.length; i++) {
quoted[i] = quoted(str[i]);
}
return StringUtils.join(keyValue, ".", startIndex, endIndex);
return StringUtils.join(quoted, ",");
}
private String getQualifiedAttributeNameFromType(AtlasEntityType t, String item) {
try {
return (t != null) ? t.getQualifiedAttributeName(item) : item;
} catch (AtlasBaseException e) {
addError(e.getMessage());
@Override
public boolean isTraitType(Context context) {
return (context.getActiveType() != null &&
context.getActiveType().getTypeCategory() == TypeCategory.CLASSIFICATION);
}
@Override
public String getTypeFromEdge(Context context, String item) {
AtlasEntityType et = context.getActiveEntityType();
if(et == null) {
return "";
}
return item;
AtlasStructType.AtlasAttribute attr = et.getAttribute(item);
if(attr == null) {
return null;
}
public String getTypeFromEdge(String item) {
AtlasType at = activeType.getAttribute(item).getAttributeType();
AtlasType at = attr.getAttributeType();
if(at.getTypeCategory() == TypeCategory.ARRAY) {
AtlasArrayType arrType = ((AtlasArrayType)at);
return ((AtlasBuiltInTypes.AtlasObjectIdType) arrType.getElementType()).getObjectType();
}
return activeType.getAttribute(item).getTypeName();
}
public boolean doesActiveTypeHaveSubTypes() {
return (activeType.getAllSubTypes().size() != 0);
return context.getActiveEntityType().getAttribute(item).getTypeName();
}
public String getActiveTypeAndSubTypes() {
Set<String> set = activeType.getTypeAndAllSubTypes();
String[] str = set.toArray(new String[]{});
for (int i = 0; i < str.length; i++) {
str[i] = String.format("'%s'", str[i]);
@Override
public boolean isDate(Context context, String attributeName) {
AtlasEntityType et = context.getActiveEntityType();
if(et == null) {
return false;
}
return StringUtils.join(str, ",");
AtlasType attr = et.getAttributeType(attributeName);
if(attr == null) {
return false;
}
public boolean isSameAsActive(String typeName) {
return (activeType != null) && activeType.getTypeName().equalsIgnoreCase(typeName);
return attr.getTypeName().equals("date");
}
}
}
// Generated from AtlasDSLLexer.g4 by ANTLR 4.7
// Generated from repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.g4 by ANTLR 4.7
package org.apache.atlas.query.antlr4;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
......
......@@ -20,8 +20,6 @@ parser grammar AtlasDSLParser;
options { tokenVocab=AtlasDSLLexer; }
// Start of rules, bottom-up (rules at the end are built using the core rules)
// Core rules
identifier: ID ;
......@@ -98,8 +96,6 @@ selectClause: K_SELECT selectExpr ;
singleQrySrc: fromClause | whereClause | fromExpression | expr ;
loopExpression: K_LOOP K_LPAREN query K_RPAREN NUMBER? (K_AS identifier)? ;
groupByExpression: K_GROUPBY K_LPAREN selectExpr K_RPAREN ;
commaDelimitedQueries: singleQrySrc (K_COMMA singleQrySrc)* ;
......@@ -108,10 +104,7 @@ spaceDelimitedQueries: singleQrySrc singleQrySrc* ;
querySrc: commaDelimitedQueries | spaceDelimitedQueries ;
query: querySrc loopExpression?
groupByExpression?
query: querySrc groupByExpression?
selectClause?
orderByExpr?
limitOffset? ;
queryWithPath: query (K_WITHPATH)? ;
// Generated from AtlasDSLParser.g4 by ANTLR 4.7
// Generated from repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLParser.g4 by ANTLR 4.7
package org.apache.atlas.query.antlr4;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
......@@ -34,9 +34,9 @@ public class AtlasDSLParser extends Parser {
RULE_compE = 20, RULE_expr = 21, RULE_limitOffset = 22, RULE_selectExpression = 23,
RULE_selectExpr = 24, RULE_aliasExpr = 25, RULE_orderByExpr = 26, RULE_fromSrc = 27,
RULE_whereClause = 28, RULE_fromExpression = 29, RULE_fromClause = 30,
RULE_selectClause = 31, RULE_singleQrySrc = 32, RULE_loopExpression = 33,
RULE_groupByExpression = 34, RULE_commaDelimitedQueries = 35, RULE_spaceDelimitedQueries = 36,
RULE_querySrc = 37, RULE_query = 38, RULE_queryWithPath = 39;
RULE_selectClause = 31, RULE_singleQrySrc = 32, RULE_groupByExpression = 33,
RULE_commaDelimitedQueries = 34, RULE_spaceDelimitedQueries = 35, RULE_querySrc = 36,
RULE_query = 37;
public static final String[] ruleNames = {
"identifier", "operator", "sortOrder", "valueArray", "literal", "limitClause",
"offsetClause", "atomE", "multiERight", "multiE", "arithERight", "arithE",
......@@ -44,8 +44,8 @@ public class AtlasDSLParser extends Parser {
"minClause", "sumClause", "exprRight", "compE", "expr", "limitOffset",
"selectExpression", "selectExpr", "aliasExpr", "orderByExpr", "fromSrc",
"whereClause", "fromExpression", "fromClause", "selectClause", "singleQrySrc",
"loopExpression", "groupByExpression", "commaDelimitedQueries", "spaceDelimitedQueries",
"querySrc", "query", "queryWithPath"
"groupByExpression", "commaDelimitedQueries", "spaceDelimitedQueries",
"querySrc", "query"
};
private static final String[] _LITERAL_NAMES = {
......@@ -129,7 +129,7 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(80);
setState(76);
match(ID);
}
}
......@@ -170,7 +170,7 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(82);
setState(78);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << K_LIKE) | (1L << K_LT) | (1L << K_LTE) | (1L << K_EQ) | (1L << K_NEQ) | (1L << K_GT) | (1L << K_GTE))) != 0)) ) {
_errHandler.recoverInline(this);
......@@ -214,7 +214,7 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(84);
setState(80);
_la = _input.LA(1);
if ( !(_la==K_ASC || _la==K_DESC) ) {
_errHandler.recoverInline(this);
......@@ -266,27 +266,27 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(86);
setState(82);
match(K_LBRACKET);
setState(87);
setState(83);
match(STRING);
setState(92);
setState(88);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==K_COMMA) {
{
{
setState(88);
setState(84);
match(K_COMMA);
setState(89);
setState(85);
match(STRING);
}
}
setState(94);
setState(90);
_errHandler.sync(this);
_la = _input.LA(1);
}
setState(95);
setState(91);
match(K_RBRACKET);
}
}
......@@ -324,27 +324,27 @@ public class AtlasDSLParser extends Parser {
LiteralContext _localctx = new LiteralContext(_ctx, getState());
enterRule(_localctx, 8, RULE_literal);
try {
setState(104);
setState(100);
_errHandler.sync(this);
switch (_input.LA(1)) {
case BOOL:
enterOuterAlt(_localctx, 1);
{
setState(97);
setState(93);
match(BOOL);
}
break;
case NUMBER:
enterOuterAlt(_localctx, 2);
{
setState(98);
setState(94);
match(NUMBER);
}
break;
case FLOATING_NUMBER:
enterOuterAlt(_localctx, 3);
{
setState(99);
setState(95);
match(FLOATING_NUMBER);
}
break;
......@@ -352,18 +352,18 @@ public class AtlasDSLParser extends Parser {
case STRING:
enterOuterAlt(_localctx, 4);
{
setState(102);
setState(98);
_errHandler.sync(this);
switch (_input.LA(1)) {
case STRING:
{
setState(100);
setState(96);
match(STRING);
}
break;
case K_LBRACKET:
{
setState(101);
setState(97);
valueArray();
}
break;
......@@ -407,9 +407,9 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(106);
setState(102);
match(K_LIMIT);
setState(107);
setState(103);
match(NUMBER);
}
}
......@@ -444,9 +444,9 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(109);
setState(105);
match(K_OFFSET);
setState(110);
setState(106);
match(NUMBER);
}
}
......@@ -488,7 +488,7 @@ public class AtlasDSLParser extends Parser {
AtomEContext _localctx = new AtomEContext(_ctx, getState());
enterRule(_localctx, 14, RULE_atomE);
try {
setState(120);
setState(116);
_errHandler.sync(this);
switch (_input.LA(1)) {
case NUMBER:
......@@ -499,12 +499,12 @@ public class AtlasDSLParser extends Parser {
case STRING:
enterOuterAlt(_localctx, 1);
{
setState(114);
setState(110);
_errHandler.sync(this);
switch (_input.LA(1)) {
case ID:
{
setState(112);
setState(108);
identifier();
}
break;
......@@ -514,7 +514,7 @@ public class AtlasDSLParser extends Parser {
case K_LBRACKET:
case STRING:
{
setState(113);
setState(109);
literal();
}
break;
......@@ -526,11 +526,11 @@ public class AtlasDSLParser extends Parser {
case K_LPAREN:
enterOuterAlt(_localctx, 2);
{
setState(116);
setState(112);
match(K_LPAREN);
setState(117);
setState(113);
expr();
setState(118);
setState(114);
match(K_RPAREN);
}
break;
......@@ -573,7 +573,7 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(122);
setState(118);
_la = _input.LA(1);
if ( !(_la==K_STAR || _la==K_DIV) ) {
_errHandler.recoverInline(this);
......@@ -583,7 +583,7 @@ public class AtlasDSLParser extends Parser {
_errHandler.reportMatch(this);
consume();
}
setState(123);
setState(119);
atomE();
}
}
......@@ -626,19 +626,19 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(125);
setState(121);
atomE();
setState(129);
setState(125);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==K_STAR || _la==K_DIV) {
{
{
setState(126);
setState(122);
multiERight();
}
}
setState(131);
setState(127);
_errHandler.sync(this);
_la = _input.LA(1);
}
......@@ -679,7 +679,7 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(132);
setState(128);
_la = _input.LA(1);
if ( !(_la==K_PLUS || _la==K_MINUS) ) {
_errHandler.recoverInline(this);
......@@ -689,7 +689,7 @@ public class AtlasDSLParser extends Parser {
_errHandler.reportMatch(this);
consume();
}
setState(133);
setState(129);
multiE();
}
}
......@@ -732,19 +732,19 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(135);
setState(131);
multiE();
setState(139);
setState(135);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==K_PLUS || _la==K_MINUS) {
{
{
setState(136);
setState(132);
arithERight();
}
}
setState(141);
setState(137);
_errHandler.sync(this);
_la = _input.LA(1);
}
......@@ -788,11 +788,11 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(142);
setState(138);
arithE();
setState(143);
setState(139);
operator();
setState(144);
setState(140);
arithE();
}
}
......@@ -834,9 +834,9 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(146);
setState(142);
arithE();
setState(147);
setState(143);
_la = _input.LA(1);
if ( !(_la==K_ISA || _la==K_IS) ) {
_errHandler.recoverInline(this);
......@@ -846,7 +846,7 @@ public class AtlasDSLParser extends Parser {
_errHandler.reportMatch(this);
consume();
}
setState(148);
setState(144);
identifier();
}
}
......@@ -886,11 +886,11 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(150);
setState(146);
arithE();
setState(151);
setState(147);
match(K_HAS);
setState(152);
setState(148);
identifier();
}
}
......@@ -926,11 +926,11 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(154);
setState(150);
match(K_COUNT);
setState(155);
setState(151);
match(K_LPAREN);
setState(156);
setState(152);
match(K_RPAREN);
}
}
......@@ -969,13 +969,13 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(158);
setState(154);
match(K_MAX);
setState(159);
setState(155);
match(K_LPAREN);
setState(160);
setState(156);
expr();
setState(161);
setState(157);
match(K_RPAREN);
}
}
......@@ -1014,13 +1014,13 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(163);
setState(159);
match(K_MIN);
setState(164);
setState(160);
match(K_LPAREN);
setState(165);
setState(161);
expr();
setState(166);
setState(162);
match(K_RPAREN);
}
}
......@@ -1059,13 +1059,13 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(168);
setState(164);
match(K_SUM);
setState(169);
setState(165);
match(K_LPAREN);
setState(170);
setState(166);
expr();
setState(171);
setState(167);
match(K_RPAREN);
}
}
......@@ -1104,7 +1104,7 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(173);
setState(169);
_la = _input.LA(1);
if ( !(_la==K_AND || _la==K_OR) ) {
_errHandler.recoverInline(this);
......@@ -1114,7 +1114,7 @@ public class AtlasDSLParser extends Parser {
_errHandler.reportMatch(this);
consume();
}
setState(174);
setState(170);
compE();
}
}
......@@ -1169,62 +1169,62 @@ public class AtlasDSLParser extends Parser {
CompEContext _localctx = new CompEContext(_ctx, getState());
enterRule(_localctx, 40, RULE_compE);
try {
setState(184);
setState(180);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
setState(176);
setState(172);
comparisonClause();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
setState(177);
setState(173);
isClause();
}
break;
case 3:
enterOuterAlt(_localctx, 3);
{
setState(178);
setState(174);
hasClause();
}
break;
case 4:
enterOuterAlt(_localctx, 4);
{
setState(179);
setState(175);
arithE();
}
break;
case 5:
enterOuterAlt(_localctx, 5);
{
setState(180);
setState(176);
countClause();
}
break;
case 6:
enterOuterAlt(_localctx, 6);
{
setState(181);
setState(177);
maxClause();
}
break;
case 7:
enterOuterAlt(_localctx, 7);
{
setState(182);
setState(178);
minClause();
}
break;
case 8:
enterOuterAlt(_localctx, 8);
{
setState(183);
setState(179);
sumClause();
}
break;
......@@ -1269,19 +1269,19 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(186);
setState(182);
compE();
setState(190);
setState(186);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==K_AND || _la==K_OR) {
{
{
setState(187);
setState(183);
exprRight();
}
}
setState(192);
setState(188);
_errHandler.sync(this);
_la = _input.LA(1);
}
......@@ -1323,14 +1323,14 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(193);
setState(189);
limitClause();
setState(195);
setState(191);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_OFFSET) {
{
setState(194);
setState(190);
offsetClause();
}
}
......@@ -1374,16 +1374,16 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(197);
setState(193);
expr();
setState(200);
setState(196);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_AS) {
{
setState(198);
setState(194);
match(K_AS);
setState(199);
setState(195);
identifier();
}
}
......@@ -1430,21 +1430,21 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(202);
setState(198);
selectExpression();
setState(207);
setState(203);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==K_COMMA) {
{
{
setState(203);
setState(199);
match(K_COMMA);
setState(204);
setState(200);
selectExpression();
}
}
setState(209);
setState(205);
_errHandler.sync(this);
_la = _input.LA(1);
}
......@@ -1489,12 +1489,12 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(212);
setState(208);
_errHandler.sync(this);
switch (_input.LA(1)) {
case ID:
{
setState(210);
setState(206);
identifier();
}
break;
......@@ -1504,16 +1504,16 @@ public class AtlasDSLParser extends Parser {
case K_LBRACKET:
case STRING:
{
setState(211);
setState(207);
literal();
}
break;
default:
throw new NoViableAltException(this);
}
setState(214);
setState(210);
match(K_AS);
setState(215);
setState(211);
identifier();
}
}
......@@ -1554,16 +1554,16 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(217);
setState(213);
match(K_ORDERBY);
setState(218);
setState(214);
expr();
setState(220);
setState(216);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_ASC || _la==K_DESC) {
{
setState(219);
setState(215);
sortOrder();
}
}
......@@ -1606,25 +1606,25 @@ public class AtlasDSLParser extends Parser {
FromSrcContext _localctx = new FromSrcContext(_ctx, getState());
enterRule(_localctx, 54, RULE_fromSrc);
try {
setState(227);
setState(223);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,15,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
setState(222);
setState(218);
aliasExpr();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
setState(225);
setState(221);
_errHandler.sync(this);
switch (_input.LA(1)) {
case ID:
{
setState(223);
setState(219);
identifier();
}
break;
......@@ -1634,7 +1634,7 @@ public class AtlasDSLParser extends Parser {
case K_LBRACKET:
case STRING:
{
setState(224);
setState(220);
literal();
}
break;
......@@ -1678,9 +1678,9 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(229);
setState(225);
match(K_WHERE);
setState(230);
setState(226);
expr();
}
}
......@@ -1719,14 +1719,14 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(232);
setState(228);
fromSrc();
setState(234);
setState(230);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) {
case 1:
{
setState(233);
setState(229);
whereClause();
}
break;
......@@ -1766,9 +1766,9 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(236);
setState(232);
match(K_FROM);
setState(237);
setState(233);
fromExpression();
}
}
......@@ -1805,9 +1805,9 @@ public class AtlasDSLParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(239);
setState(235);
match(K_SELECT);
setState(240);
setState(236);
selectExpr();
}
}
......@@ -1850,34 +1850,34 @@ public class AtlasDSLParser extends Parser {
SingleQrySrcContext _localctx = new SingleQrySrcContext(_ctx, getState());
enterRule(_localctx, 64, RULE_singleQrySrc);
try {
setState(246);
setState(242);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
setState(242);
setState(238);
fromClause();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
setState(243);
setState(239);
whereClause();
}
break;
case 3:
enterOuterAlt(_localctx, 3);
{
setState(244);
setState(240);
fromExpression();
}
break;
case 4:
enterOuterAlt(_localctx, 4);
{
setState(245);
setState(241);
expr();
}
break;
......@@ -1894,79 +1894,6 @@ public class AtlasDSLParser extends Parser {
return _localctx;
}
public static class LoopExpressionContext extends ParserRuleContext {
public TerminalNode K_LOOP() { return getToken(AtlasDSLParser.K_LOOP, 0); }
public TerminalNode K_LPAREN() { return getToken(AtlasDSLParser.K_LPAREN, 0); }
public QueryContext query() {
return getRuleContext(QueryContext.class,0);
}
public TerminalNode K_RPAREN() { return getToken(AtlasDSLParser.K_RPAREN, 0); }
public TerminalNode NUMBER() { return getToken(AtlasDSLParser.NUMBER, 0); }
public TerminalNode K_AS() { return getToken(AtlasDSLParser.K_AS, 0); }
public IdentifierContext identifier() {
return getRuleContext(IdentifierContext.class,0);
}
public LoopExpressionContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_loopExpression; }
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof AtlasDSLParserVisitor ) return ((AtlasDSLParserVisitor<? extends T>)visitor).visitLoopExpression(this);
else return visitor.visitChildren(this);
}
}
public final LoopExpressionContext loopExpression() throws RecognitionException {
LoopExpressionContext _localctx = new LoopExpressionContext(_ctx, getState());
enterRule(_localctx, 66, RULE_loopExpression);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(248);
match(K_LOOP);
setState(249);
match(K_LPAREN);
setState(250);
query();
setState(251);
match(K_RPAREN);
setState(253);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==NUMBER) {
{
setState(252);
match(NUMBER);
}
}
setState(257);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_AS) {
{
setState(255);
match(K_AS);
setState(256);
identifier();
}
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class GroupByExpressionContext extends ParserRuleContext {
public TerminalNode K_GROUPBY() { return getToken(AtlasDSLParser.K_GROUPBY, 0); }
public TerminalNode K_LPAREN() { return getToken(AtlasDSLParser.K_LPAREN, 0); }
......@@ -1987,17 +1914,17 @@ public class AtlasDSLParser extends Parser {
public final GroupByExpressionContext groupByExpression() throws RecognitionException {
GroupByExpressionContext _localctx = new GroupByExpressionContext(_ctx, getState());
enterRule(_localctx, 68, RULE_groupByExpression);
enterRule(_localctx, 66, RULE_groupByExpression);
try {
enterOuterAlt(_localctx, 1);
{
setState(259);
setState(244);
match(K_GROUPBY);
setState(260);
setState(245);
match(K_LPAREN);
setState(261);
setState(246);
selectExpr();
setState(262);
setState(247);
match(K_RPAREN);
}
}
......@@ -2036,26 +1963,26 @@ public class AtlasDSLParser extends Parser {
public final CommaDelimitedQueriesContext commaDelimitedQueries() throws RecognitionException {
CommaDelimitedQueriesContext _localctx = new CommaDelimitedQueriesContext(_ctx, getState());
enterRule(_localctx, 70, RULE_commaDelimitedQueries);
enterRule(_localctx, 68, RULE_commaDelimitedQueries);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(264);
setState(249);
singleQrySrc();
setState(269);
setState(254);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==K_COMMA) {
{
{
setState(265);
setState(250);
match(K_COMMA);
setState(266);
setState(251);
singleQrySrc();
}
}
setState(271);
setState(256);
_errHandler.sync(this);
_la = _input.LA(1);
}
......@@ -2092,24 +2019,24 @@ public class AtlasDSLParser extends Parser {
public final SpaceDelimitedQueriesContext spaceDelimitedQueries() throws RecognitionException {
SpaceDelimitedQueriesContext _localctx = new SpaceDelimitedQueriesContext(_ctx, getState());
enterRule(_localctx, 72, RULE_spaceDelimitedQueries);
enterRule(_localctx, 70, RULE_spaceDelimitedQueries);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(272);
setState(257);
singleQrySrc();
setState(276);
setState(261);
_errHandler.sync(this);
_la = _input.LA(1);
while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << NUMBER) | (1L << FLOATING_NUMBER) | (1L << BOOL) | (1L << K_LPAREN) | (1L << K_LBRACKET) | (1L << K_FROM) | (1L << K_WHERE) | (1L << K_MAX) | (1L << K_MIN) | (1L << K_SUM) | (1L << K_COUNT) | (1L << ID) | (1L << STRING))) != 0)) {
{
{
setState(273);
setState(258);
singleQrySrc();
}
}
setState(278);
setState(263);
_errHandler.sync(this);
_la = _input.LA(1);
}
......@@ -2146,22 +2073,22 @@ public class AtlasDSLParser extends Parser {
public final QuerySrcContext querySrc() throws RecognitionException {
QuerySrcContext _localctx = new QuerySrcContext(_ctx, getState());
enterRule(_localctx, 74, RULE_querySrc);
enterRule(_localctx, 72, RULE_querySrc);
try {
setState(281);
setState(266);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,22,_ctx) ) {
switch ( getInterpreter().adaptivePredict(_input,20,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
setState(279);
setState(264);
commaDelimitedQueries();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
setState(280);
setState(265);
spaceDelimitedQueries();
}
break;
......@@ -2182,9 +2109,6 @@ public class AtlasDSLParser extends Parser {
public QuerySrcContext querySrc() {
return getRuleContext(QuerySrcContext.class,0);
}
public LoopExpressionContext loopExpression() {
return getRuleContext(LoopExpressionContext.class,0);
}
public GroupByExpressionContext groupByExpression() {
return getRuleContext(GroupByExpressionContext.class,0);
}
......@@ -2210,59 +2134,49 @@ public class AtlasDSLParser extends Parser {
public final QueryContext query() throws RecognitionException {
QueryContext _localctx = new QueryContext(_ctx, getState());
enterRule(_localctx, 76, RULE_query);
enterRule(_localctx, 74, RULE_query);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(283);
setState(268);
querySrc();
setState(285);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_LOOP) {
{
setState(284);
loopExpression();
}
}
setState(288);
setState(270);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_GROUPBY) {
{
setState(287);
setState(269);
groupByExpression();
}
}
setState(291);
setState(273);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_SELECT) {
{
setState(290);
setState(272);
selectClause();
}
}
setState(294);
setState(276);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_ORDERBY) {
{
setState(293);
setState(275);
orderByExpr();
}
}
setState(297);
setState(279);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_LIMIT) {
{
setState(296);
setState(278);
limitOffset();
}
}
......@@ -2280,156 +2194,99 @@ public class AtlasDSLParser extends Parser {
return _localctx;
}
public static class QueryWithPathContext extends ParserRuleContext {
public QueryContext query() {
return getRuleContext(QueryContext.class,0);
}
public TerminalNode K_WITHPATH() { return getToken(AtlasDSLParser.K_WITHPATH, 0); }
public QueryWithPathContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_queryWithPath; }
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof AtlasDSLParserVisitor ) return ((AtlasDSLParserVisitor<? extends T>)visitor).visitQueryWithPath(this);
else return visitor.visitChildren(this);
}
}
public final QueryWithPathContext queryWithPath() throws RecognitionException {
QueryWithPathContext _localctx = new QueryWithPathContext(_ctx, getState());
enterRule(_localctx, 78, RULE_queryWithPath);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(299);
query();
setState(301);
_errHandler.sync(this);
_la = _input.LA(1);
if (_la==K_WITHPATH) {
{
setState(300);
match(K_WITHPATH);
}
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\63\u0132\4\2\t\2"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\63\u011c\4\2\t\2"+
"\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\3\2\3\2\3\3\3"+
"\3\3\4\3\4\3\5\3\5\3\5\3\5\7\5]\n\5\f\5\16\5`\13\5\3\5\3\5\3\6\3\6\3\6"+
"\3\6\3\6\5\6i\n\6\5\6k\n\6\3\7\3\7\3\7\3\b\3\b\3\b\3\t\3\t\5\tu\n\t\3"+
"\t\3\t\3\t\3\t\5\t{\n\t\3\n\3\n\3\n\3\13\3\13\7\13\u0082\n\13\f\13\16"+
"\13\u0085\13\13\3\f\3\f\3\f\3\r\3\r\7\r\u008c\n\r\f\r\16\r\u008f\13\r"+
"\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\21\3\21"+
"\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24"+
"\3\24\3\24\3\24\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+
"\5\26\u00bb\n\26\3\27\3\27\7\27\u00bf\n\27\f\27\16\27\u00c2\13\27\3\30"+
"\3\30\5\30\u00c6\n\30\3\31\3\31\3\31\5\31\u00cb\n\31\3\32\3\32\3\32\7"+
"\32\u00d0\n\32\f\32\16\32\u00d3\13\32\3\33\3\33\5\33\u00d7\n\33\3\33\3"+
"\33\3\33\3\34\3\34\3\34\5\34\u00df\n\34\3\35\3\35\3\35\5\35\u00e4\n\35"+
"\5\35\u00e6\n\35\3\36\3\36\3\36\3\37\3\37\5\37\u00ed\n\37\3 \3 \3 \3!"+
"\3!\3!\3\"\3\"\3\"\3\"\5\"\u00f9\n\"\3#\3#\3#\3#\3#\5#\u0100\n#\3#\3#"+
"\5#\u0104\n#\3$\3$\3$\3$\3$\3%\3%\3%\7%\u010e\n%\f%\16%\u0111\13%\3&\3"+
"&\7&\u0115\n&\f&\16&\u0118\13&\3\'\3\'\5\'\u011c\n\'\3(\3(\5(\u0120\n"+
"(\3(\5(\u0123\n(\3(\5(\u0126\n(\3(\5(\u0129\n(\3(\5(\u012c\n(\3)\3)\5"+
")\u0130\n)\3)\2\2*\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+
"\62\64\668:<>@BDFHJLNP\2\b\4\2\17\17\26\33\3\2,-\3\2\f\r\3\2\n\13\3\2"+
")*\3\2\20\21\2\u0130\2R\3\2\2\2\4T\3\2\2\2\6V\3\2\2\2\bX\3\2\2\2\nj\3"+
"\2\2\2\fl\3\2\2\2\16o\3\2\2\2\20z\3\2\2\2\22|\3\2\2\2\24\177\3\2\2\2\26"+
"\u0086\3\2\2\2\30\u0089\3\2\2\2\32\u0090\3\2\2\2\34\u0094\3\2\2\2\36\u0098"+
"\3\2\2\2 \u009c\3\2\2\2\"\u00a0\3\2\2\2$\u00a5\3\2\2\2&\u00aa\3\2\2\2"+
"(\u00af\3\2\2\2*\u00ba\3\2\2\2,\u00bc\3\2\2\2.\u00c3\3\2\2\2\60\u00c7"+
"\3\2\2\2\62\u00cc\3\2\2\2\64\u00d6\3\2\2\2\66\u00db\3\2\2\28\u00e5\3\2"+
"\2\2:\u00e7\3\2\2\2<\u00ea\3\2\2\2>\u00ee\3\2\2\2@\u00f1\3\2\2\2B\u00f8"+
"\3\2\2\2D\u00fa\3\2\2\2F\u0105\3\2\2\2H\u010a\3\2\2\2J\u0112\3\2\2\2L"+
"\u011b\3\2\2\2N\u011d\3\2\2\2P\u012d\3\2\2\2RS\7\62\2\2S\3\3\2\2\2TU\t"+
"\2\2\2U\5\3\2\2\2VW\t\3\2\2W\7\3\2\2\2XY\7\23\2\2Y^\7\63\2\2Z[\7\t\2\2"+
"[]\7\63\2\2\\Z\3\2\2\2]`\3\2\2\2^\\\3\2\2\2^_\3\2\2\2_a\3\2\2\2`^\3\2"+
"\2\2ab\7\25\2\2b\t\3\2\2\2ck\7\b\2\2dk\7\6\2\2ek\7\7\2\2fi\7\63\2\2gi"+
"\5\b\5\2hf\3\2\2\2hg\3\2\2\2ik\3\2\2\2jc\3\2\2\2jd\3\2\2\2je\3\2\2\2j"+
"h\3\2\2\2k\13\3\2\2\2lm\7 \2\2mn\7\6\2\2n\r\3\2\2\2op\7\'\2\2pq\7\6\2"+
"\2q\17\3\2\2\2ru\5\2\2\2su\5\n\6\2tr\3\2\2\2ts\3\2\2\2u{\3\2\2\2vw\7\22"+
"\2\2wx\5,\27\2xy\7\24\2\2y{\3\2\2\2zt\3\2\2\2zv\3\2\2\2{\21\3\2\2\2|}"+
"\t\4\2\2}~\5\20\t\2~\23\3\2\2\2\177\u0083\5\20\t\2\u0080\u0082\5\22\n"+
"\2\u0081\u0080\3\2\2\2\u0082\u0085\3\2\2\2\u0083\u0081\3\2\2\2\u0083\u0084"+
"\3\2\2\2\u0084\25\3\2\2\2\u0085\u0083\3\2\2\2\u0086\u0087\t\5\2\2\u0087"+
"\u0088\5\24\13\2\u0088\27\3\2\2\2\u0089\u008d\5\24\13\2\u008a\u008c\5"+
"\26\f\2\u008b\u008a\3\2\2\2\u008c\u008f\3\2\2\2\u008d\u008b\3\2\2\2\u008d"+
"\u008e\3\2\2\2\u008e\31\3\2\2\2\u008f\u008d\3\2\2\2\u0090\u0091\5\30\r"+
"\2\u0091\u0092\5\4\3\2\u0092\u0093\5\30\r\2\u0093\33\3\2\2\2\u0094\u0095"+
"\5\30\r\2\u0095\u0096\t\6\2\2\u0096\u0097\5\2\2\2\u0097\35\3\2\2\2\u0098"+
"\u0099\5\30\r\2\u0099\u009a\7+\2\2\u009a\u009b\5\2\2\2\u009b\37\3\2\2"+
"\2\u009c\u009d\7%\2\2\u009d\u009e\7\22\2\2\u009e\u009f\7\24\2\2\u009f"+
"!\3\2\2\2\u00a0\u00a1\7\"\2\2\u00a1\u00a2\7\22\2\2\u00a2\u00a3\5,\27\2"+
"\u00a3\u00a4\7\24\2\2\u00a4#\3\2\2\2\u00a5\u00a6\7#\2\2\u00a6\u00a7\7"+
"\22\2\2\u00a7\u00a8\5,\27\2\u00a8\u00a9\7\24\2\2\u00a9%\3\2\2\2\u00aa"+
"\u00ab\7$\2\2\u00ab\u00ac\7\22\2\2\u00ac\u00ad\5,\27\2\u00ad\u00ae\7\24"+
"\2\2\u00ae\'\3\2\2\2\u00af\u00b0\t\7\2\2\u00b0\u00b1\5*\26\2\u00b1)\3"+
"\2\2\2\u00b2\u00bb\5\32\16\2\u00b3\u00bb\5\34\17\2\u00b4\u00bb\5\36\20"+
"\2\u00b5\u00bb\5\30\r\2\u00b6\u00bb\5 \21\2\u00b7\u00bb\5\"\22\2\u00b8"+
"\u00bb\5$\23\2\u00b9\u00bb\5&\24\2\u00ba\u00b2\3\2\2\2\u00ba\u00b3\3\2"+
"\2\2\u00ba\u00b4\3\2\2\2\u00ba\u00b5\3\2\2\2\u00ba\u00b6\3\2\2\2\u00ba"+
"\u00b7\3\2\2\2\u00ba\u00b8\3\2\2\2\u00ba\u00b9\3\2\2\2\u00bb+\3\2\2\2"+
"\u00bc\u00c0\5*\26\2\u00bd\u00bf\5(\25\2\u00be\u00bd\3\2\2\2\u00bf\u00c2"+
"\3\2\2\2\u00c0\u00be\3\2\2\2\u00c0\u00c1\3\2\2\2\u00c1-\3\2\2\2\u00c2"+
"\u00c0\3\2\2\2\u00c3\u00c5\5\f\7\2\u00c4\u00c6\5\16\b\2\u00c5\u00c4\3"+
"\2\2\2\u00c5\u00c6\3\2\2\2\u00c6/\3\2\2\2\u00c7\u00ca\5,\27\2\u00c8\u00c9"+
"\7(\2\2\u00c9\u00cb\5\2\2\2\u00ca\u00c8\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb"+
"\61\3\2\2\2\u00cc\u00d1\5\60\31\2\u00cd\u00ce\7\t\2\2\u00ce\u00d0\5\60"+
"\31\2\u00cf\u00cd\3\2\2\2\u00d0\u00d3\3\2\2\2\u00d1\u00cf\3\2\2\2\u00d1"+
"\u00d2\3\2\2\2\u00d2\63\3\2\2\2\u00d3\u00d1\3\2\2\2\u00d4\u00d7\5\2\2"+
"\2\u00d5\u00d7\5\n\6\2\u00d6\u00d4\3\2\2\2\u00d6\u00d5\3\2\2\2\u00d7\u00d8"+
"\3\2\2\2\u00d8\u00d9\7(\2\2\u00d9\u00da\5\2\2\2\u00da\65\3\2\2\2\u00db"+
"\u00dc\7\36\2\2\u00dc\u00de\5,\27\2\u00dd\u00df\5\6\4\2\u00de\u00dd\3"+
"\2\2\2\u00de\u00df\3\2\2\2\u00df\67\3\2\2\2\u00e0\u00e6\5\64\33\2\u00e1"+
"\u00e4\5\2\2\2\u00e2\u00e4\5\n\6\2\u00e3\u00e1\3\2\2\2\u00e3\u00e2\3\2"+
"\2\2\u00e4\u00e6\3\2\2\2\u00e5\u00e0\3\2\2\2\u00e5\u00e3\3\2\2\2\u00e6"+
"9\3\2\2\2\u00e7\u00e8\7\35\2\2\u00e8\u00e9\5,\27\2\u00e9;\3\2\2\2\u00ea"+
"\u00ec\58\35\2\u00eb\u00ed\5:\36\2\u00ec\u00eb\3\2\2\2\u00ec\u00ed\3\2"+
"\2\2\u00ed=\3\2\2\2\u00ee\u00ef\7\34\2\2\u00ef\u00f0\5<\37\2\u00f0?\3"+
"\2\2\2\u00f1\u00f2\7!\2\2\u00f2\u00f3\5\62\32\2\u00f3A\3\2\2\2\u00f4\u00f9"+
"\5> \2\u00f5\u00f9\5:\36\2\u00f6\u00f9\5<\37\2\u00f7\u00f9\5,\27\2\u00f8"+
"\u00f4\3\2\2\2\u00f8\u00f5\3\2\2\2\u00f8\u00f6\3\2\2\2\u00f8\u00f7\3\2"+
"\2\2\u00f9C\3\2\2\2\u00fa\u00fb\7&\2\2\u00fb\u00fc\7\22\2\2\u00fc\u00fd"+
"\5N(\2\u00fd\u00ff\7\24\2\2\u00fe\u0100\7\6\2\2\u00ff\u00fe\3\2\2\2\u00ff"+
"\u0100\3\2\2\2\u0100\u0103\3\2\2\2\u0101\u0102\7(\2\2\u0102\u0104\5\2"+
"\2\2\u0103\u0101\3\2\2\2\u0103\u0104\3\2\2\2\u0104E\3\2\2\2\u0105\u0106"+
"\7\37\2\2\u0106\u0107\7\22\2\2\u0107\u0108\5\62\32\2\u0108\u0109\7\24"+
"\2\2\u0109G\3\2\2\2\u010a\u010f\5B\"\2\u010b\u010c\7\t\2\2\u010c\u010e"+
"\5B\"\2\u010d\u010b\3\2\2\2\u010e\u0111\3\2\2\2\u010f\u010d\3\2\2\2\u010f"+
"\u0110\3\2\2\2\u0110I\3\2\2\2\u0111\u010f\3\2\2\2\u0112\u0116\5B\"\2\u0113"+
"\u0115\5B\"\2\u0114\u0113\3\2\2\2\u0115\u0118\3\2\2\2\u0116\u0114\3\2"+
"\2\2\u0116\u0117\3\2\2\2\u0117K\3\2\2\2\u0118\u0116\3\2\2\2\u0119\u011c"+
"\5H%\2\u011a\u011c\5J&\2\u011b\u0119\3\2\2\2\u011b\u011a\3\2\2\2\u011c"+
"M\3\2\2\2\u011d\u011f\5L\'\2\u011e\u0120\5D#\2\u011f\u011e\3\2\2\2\u011f"+
"\u0120\3\2\2\2\u0120\u0122\3\2\2\2\u0121\u0123\5F$\2\u0122\u0121\3\2\2"+
"\2\u0122\u0123\3\2\2\2\u0123\u0125\3\2\2\2\u0124\u0126\5@!\2\u0125\u0124"+
"\3\2\2\2\u0125\u0126\3\2\2\2\u0126\u0128\3\2\2\2\u0127\u0129\5\66\34\2"+
"\u0128\u0127\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012b\3\2\2\2\u012a\u012c"+
"\5.\30\2\u012b\u012a\3\2\2\2\u012b\u012c\3\2\2\2\u012cO\3\2\2\2\u012d"+
"\u012f\5N(\2\u012e\u0130\7.\2\2\u012f\u012e\3\2\2\2\u012f\u0130\3\2\2"+
"\2\u0130Q\3\2\2\2\37^hjtz\u0083\u008d\u00ba\u00c0\u00c5\u00ca\u00d1\u00d6"+
"\u00de\u00e3\u00e5\u00ec\u00f8\u00ff\u0103\u010f\u0116\u011b\u011f\u0122"+
"\u0125\u0128\u012b\u012f";
"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\3\2\3\2\3\3\3\3\3\4\3\4\3"+
"\5\3\5\3\5\3\5\7\5Y\n\5\f\5\16\5\\\13\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\5"+
"\6e\n\6\5\6g\n\6\3\7\3\7\3\7\3\b\3\b\3\b\3\t\3\t\5\tq\n\t\3\t\3\t\3\t"+
"\3\t\5\tw\n\t\3\n\3\n\3\n\3\13\3\13\7\13~\n\13\f\13\16\13\u0081\13\13"+
"\3\f\3\f\3\f\3\r\3\r\7\r\u0088\n\r\f\r\16\r\u008b\13\r\3\16\3\16\3\16"+
"\3\16\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\22"+
"\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24"+
"\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u00b7\n\26"+
"\3\27\3\27\7\27\u00bb\n\27\f\27\16\27\u00be\13\27\3\30\3\30\5\30\u00c2"+
"\n\30\3\31\3\31\3\31\5\31\u00c7\n\31\3\32\3\32\3\32\7\32\u00cc\n\32\f"+
"\32\16\32\u00cf\13\32\3\33\3\33\5\33\u00d3\n\33\3\33\3\33\3\33\3\34\3"+
"\34\3\34\5\34\u00db\n\34\3\35\3\35\3\35\5\35\u00e0\n\35\5\35\u00e2\n\35"+
"\3\36\3\36\3\36\3\37\3\37\5\37\u00e9\n\37\3 \3 \3 \3!\3!\3!\3\"\3\"\3"+
"\"\3\"\5\"\u00f5\n\"\3#\3#\3#\3#\3#\3$\3$\3$\7$\u00ff\n$\f$\16$\u0102"+
"\13$\3%\3%\7%\u0106\n%\f%\16%\u0109\13%\3&\3&\5&\u010d\n&\3\'\3\'\5\'"+
"\u0111\n\'\3\'\5\'\u0114\n\'\3\'\5\'\u0117\n\'\3\'\5\'\u011a\n\'\3\'\2"+
"\2(\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@B"+
"DFHJL\2\b\4\2\17\17\26\33\3\2,-\3\2\f\r\3\2\n\13\3\2)*\3\2\20\21\2\u0118"+
"\2N\3\2\2\2\4P\3\2\2\2\6R\3\2\2\2\bT\3\2\2\2\nf\3\2\2\2\fh\3\2\2\2\16"+
"k\3\2\2\2\20v\3\2\2\2\22x\3\2\2\2\24{\3\2\2\2\26\u0082\3\2\2\2\30\u0085"+
"\3\2\2\2\32\u008c\3\2\2\2\34\u0090\3\2\2\2\36\u0094\3\2\2\2 \u0098\3\2"+
"\2\2\"\u009c\3\2\2\2$\u00a1\3\2\2\2&\u00a6\3\2\2\2(\u00ab\3\2\2\2*\u00b6"+
"\3\2\2\2,\u00b8\3\2\2\2.\u00bf\3\2\2\2\60\u00c3\3\2\2\2\62\u00c8\3\2\2"+
"\2\64\u00d2\3\2\2\2\66\u00d7\3\2\2\28\u00e1\3\2\2\2:\u00e3\3\2\2\2<\u00e6"+
"\3\2\2\2>\u00ea\3\2\2\2@\u00ed\3\2\2\2B\u00f4\3\2\2\2D\u00f6\3\2\2\2F"+
"\u00fb\3\2\2\2H\u0103\3\2\2\2J\u010c\3\2\2\2L\u010e\3\2\2\2NO\7\62\2\2"+
"O\3\3\2\2\2PQ\t\2\2\2Q\5\3\2\2\2RS\t\3\2\2S\7\3\2\2\2TU\7\23\2\2UZ\7\63"+
"\2\2VW\7\t\2\2WY\7\63\2\2XV\3\2\2\2Y\\\3\2\2\2ZX\3\2\2\2Z[\3\2\2\2[]\3"+
"\2\2\2\\Z\3\2\2\2]^\7\25\2\2^\t\3\2\2\2_g\7\b\2\2`g\7\6\2\2ag\7\7\2\2"+
"be\7\63\2\2ce\5\b\5\2db\3\2\2\2dc\3\2\2\2eg\3\2\2\2f_\3\2\2\2f`\3\2\2"+
"\2fa\3\2\2\2fd\3\2\2\2g\13\3\2\2\2hi\7 \2\2ij\7\6\2\2j\r\3\2\2\2kl\7\'"+
"\2\2lm\7\6\2\2m\17\3\2\2\2nq\5\2\2\2oq\5\n\6\2pn\3\2\2\2po\3\2\2\2qw\3"+
"\2\2\2rs\7\22\2\2st\5,\27\2tu\7\24\2\2uw\3\2\2\2vp\3\2\2\2vr\3\2\2\2w"+
"\21\3\2\2\2xy\t\4\2\2yz\5\20\t\2z\23\3\2\2\2{\177\5\20\t\2|~\5\22\n\2"+
"}|\3\2\2\2~\u0081\3\2\2\2\177}\3\2\2\2\177\u0080\3\2\2\2\u0080\25\3\2"+
"\2\2\u0081\177\3\2\2\2\u0082\u0083\t\5\2\2\u0083\u0084\5\24\13\2\u0084"+
"\27\3\2\2\2\u0085\u0089\5\24\13\2\u0086\u0088\5\26\f\2\u0087\u0086\3\2"+
"\2\2\u0088\u008b\3\2\2\2\u0089\u0087\3\2\2\2\u0089\u008a\3\2\2\2\u008a"+
"\31\3\2\2\2\u008b\u0089\3\2\2\2\u008c\u008d\5\30\r\2\u008d\u008e\5\4\3"+
"\2\u008e\u008f\5\30\r\2\u008f\33\3\2\2\2\u0090\u0091\5\30\r\2\u0091\u0092"+
"\t\6\2\2\u0092\u0093\5\2\2\2\u0093\35\3\2\2\2\u0094\u0095\5\30\r\2\u0095"+
"\u0096\7+\2\2\u0096\u0097\5\2\2\2\u0097\37\3\2\2\2\u0098\u0099\7%\2\2"+
"\u0099\u009a\7\22\2\2\u009a\u009b\7\24\2\2\u009b!\3\2\2\2\u009c\u009d"+
"\7\"\2\2\u009d\u009e\7\22\2\2\u009e\u009f\5,\27\2\u009f\u00a0\7\24\2\2"+
"\u00a0#\3\2\2\2\u00a1\u00a2\7#\2\2\u00a2\u00a3\7\22\2\2\u00a3\u00a4\5"+
",\27\2\u00a4\u00a5\7\24\2\2\u00a5%\3\2\2\2\u00a6\u00a7\7$\2\2\u00a7\u00a8"+
"\7\22\2\2\u00a8\u00a9\5,\27\2\u00a9\u00aa\7\24\2\2\u00aa\'\3\2\2\2\u00ab"+
"\u00ac\t\7\2\2\u00ac\u00ad\5*\26\2\u00ad)\3\2\2\2\u00ae\u00b7\5\32\16"+
"\2\u00af\u00b7\5\34\17\2\u00b0\u00b7\5\36\20\2\u00b1\u00b7\5\30\r\2\u00b2"+
"\u00b7\5 \21\2\u00b3\u00b7\5\"\22\2\u00b4\u00b7\5$\23\2\u00b5\u00b7\5"+
"&\24\2\u00b6\u00ae\3\2\2\2\u00b6\u00af\3\2\2\2\u00b6\u00b0\3\2\2\2\u00b6"+
"\u00b1\3\2\2\2\u00b6\u00b2\3\2\2\2\u00b6\u00b3\3\2\2\2\u00b6\u00b4\3\2"+
"\2\2\u00b6\u00b5\3\2\2\2\u00b7+\3\2\2\2\u00b8\u00bc\5*\26\2\u00b9\u00bb"+
"\5(\25\2\u00ba\u00b9\3\2\2\2\u00bb\u00be\3\2\2\2\u00bc\u00ba\3\2\2\2\u00bc"+
"\u00bd\3\2\2\2\u00bd-\3\2\2\2\u00be\u00bc\3\2\2\2\u00bf\u00c1\5\f\7\2"+
"\u00c0\u00c2\5\16\b\2\u00c1\u00c0\3\2\2\2\u00c1\u00c2\3\2\2\2\u00c2/\3"+
"\2\2\2\u00c3\u00c6\5,\27\2\u00c4\u00c5\7(\2\2\u00c5\u00c7\5\2\2\2\u00c6"+
"\u00c4\3\2\2\2\u00c6\u00c7\3\2\2\2\u00c7\61\3\2\2\2\u00c8\u00cd\5\60\31"+
"\2\u00c9\u00ca\7\t\2\2\u00ca\u00cc\5\60\31\2\u00cb\u00c9\3\2\2\2\u00cc"+
"\u00cf\3\2\2\2\u00cd\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\63\3\2\2"+
"\2\u00cf\u00cd\3\2\2\2\u00d0\u00d3\5\2\2\2\u00d1\u00d3\5\n\6\2\u00d2\u00d0"+
"\3\2\2\2\u00d2\u00d1\3\2\2\2\u00d3\u00d4\3\2\2\2\u00d4\u00d5\7(\2\2\u00d5"+
"\u00d6\5\2\2\2\u00d6\65\3\2\2\2\u00d7\u00d8\7\36\2\2\u00d8\u00da\5,\27"+
"\2\u00d9\u00db\5\6\4\2\u00da\u00d9\3\2\2\2\u00da\u00db\3\2\2\2\u00db\67"+
"\3\2\2\2\u00dc\u00e2\5\64\33\2\u00dd\u00e0\5\2\2\2\u00de\u00e0\5\n\6\2"+
"\u00df\u00dd\3\2\2\2\u00df\u00de\3\2\2\2\u00e0\u00e2\3\2\2\2\u00e1\u00dc"+
"\3\2\2\2\u00e1\u00df\3\2\2\2\u00e29\3\2\2\2\u00e3\u00e4\7\35\2\2\u00e4"+
"\u00e5\5,\27\2\u00e5;\3\2\2\2\u00e6\u00e8\58\35\2\u00e7\u00e9\5:\36\2"+
"\u00e8\u00e7\3\2\2\2\u00e8\u00e9\3\2\2\2\u00e9=\3\2\2\2\u00ea\u00eb\7"+
"\34\2\2\u00eb\u00ec\5<\37\2\u00ec?\3\2\2\2\u00ed\u00ee\7!\2\2\u00ee\u00ef"+
"\5\62\32\2\u00efA\3\2\2\2\u00f0\u00f5\5> \2\u00f1\u00f5\5:\36\2\u00f2"+
"\u00f5\5<\37\2\u00f3\u00f5\5,\27\2\u00f4\u00f0\3\2\2\2\u00f4\u00f1\3\2"+
"\2\2\u00f4\u00f2\3\2\2\2\u00f4\u00f3\3\2\2\2\u00f5C\3\2\2\2\u00f6\u00f7"+
"\7\37\2\2\u00f7\u00f8\7\22\2\2\u00f8\u00f9\5\62\32\2\u00f9\u00fa\7\24"+
"\2\2\u00faE\3\2\2\2\u00fb\u0100\5B\"\2\u00fc\u00fd\7\t\2\2\u00fd\u00ff"+
"\5B\"\2\u00fe\u00fc\3\2\2\2\u00ff\u0102\3\2\2\2\u0100\u00fe\3\2\2\2\u0100"+
"\u0101\3\2\2\2\u0101G\3\2\2\2\u0102\u0100\3\2\2\2\u0103\u0107\5B\"\2\u0104"+
"\u0106\5B\"\2\u0105\u0104\3\2\2\2\u0106\u0109\3\2\2\2\u0107\u0105\3\2"+
"\2\2\u0107\u0108\3\2\2\2\u0108I\3\2\2\2\u0109\u0107\3\2\2\2\u010a\u010d"+
"\5F$\2\u010b\u010d\5H%\2\u010c\u010a\3\2\2\2\u010c\u010b\3\2\2\2\u010d"+
"K\3\2\2\2\u010e\u0110\5J&\2\u010f\u0111\5D#\2\u0110\u010f\3\2\2\2\u0110"+
"\u0111\3\2\2\2\u0111\u0113\3\2\2\2\u0112\u0114\5@!\2\u0113\u0112\3\2\2"+
"\2\u0113\u0114\3\2\2\2\u0114\u0116\3\2\2\2\u0115\u0117\5\66\34\2\u0116"+
"\u0115\3\2\2\2\u0116\u0117\3\2\2\2\u0117\u0119\3\2\2\2\u0118\u011a\5."+
"\30\2\u0119\u0118\3\2\2\2\u0119\u011a\3\2\2\2\u011aM\3\2\2\2\33Zdfpv\177"+
"\u0089\u00b6\u00bc\u00c1\u00c6\u00cd\u00d2\u00da\u00df\u00e1\u00e8\u00f4"+
"\u0100\u0107\u010c\u0110\u0113\u0116\u0119";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
......
// Generated from AtlasDSLParser.g4 by ANTLR 4.7
// Generated from repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLParser.g4 by ANTLR 4.7
package org.apache.atlas.query.antlr4;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
......@@ -248,13 +248,6 @@ public class AtlasDSLParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLoopExpression(AtlasDSLParser.LoopExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGroupByExpression(AtlasDSLParser.GroupByExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
......@@ -284,11 +277,4 @@ public class AtlasDSLParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitQuery(AtlasDSLParser.QueryContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitQueryWithPath(AtlasDSLParser.QueryWithPathContext ctx) { return visitChildren(ctx); }
}
\ No newline at end of file
// Generated from AtlasDSLParser.g4 by ANTLR 4.7
// Generated from repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLParser.g4 by ANTLR 4.7
package org.apache.atlas.query.antlr4;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
......@@ -209,12 +209,6 @@ public interface AtlasDSLParserVisitor<T> extends ParseTreeVisitor<T> {
*/
T visitSingleQrySrc(AtlasDSLParser.SingleQrySrcContext ctx);
/**
* Visit a parse tree produced by {@link AtlasDSLParser#loopExpression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLoopExpression(AtlasDSLParser.LoopExpressionContext ctx);
/**
* Visit a parse tree produced by {@link AtlasDSLParser#groupByExpression}.
* @param ctx the parse tree
* @return the visitor result
......@@ -244,10 +238,4 @@ public interface AtlasDSLParserVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result
*/
T visitQuery(AtlasDSLParser.QueryContext ctx);
/**
* Visit a parse tree produced by {@link AtlasDSLParser#queryWithPath}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitQueryWithPath(AtlasDSLParser.QueryWithPathContext ctx);
}
\ No newline at end of file
......@@ -23,17 +23,18 @@ import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.typedef.*;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityStream;
import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.AtlasTypeUtil;
import javax.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
......@@ -46,17 +47,24 @@ public abstract class BasicTestSetup {
protected static final String HIVE_TABLE_TYPE = "hive_table";
private static final String COLUMN_TYPE = "hive_column";
private static final String HIVE_PROCESS_TYPE = "hive_process";
private static final String STORAGE_DESC_TYPE = "StorageDesc";
private static final String VIEW_TYPE = "View";
private static final String PARTITION_TYPE = "hive_partition";
protected static final String DATASET_SUBTYPE = "dataset_subtype";
private static final String STORAGE_DESC_TYPE = "hive_storagedesc";
private static final String VIEW_TYPE = "hive_process";
protected static final String DATASET_SUBTYPE = "Asset";
public static final String DIMENSION_CLASSIFICATION = "Dimension";
public static final String FACT_CLASSIFICATION = "Fact";
public static final String PII_CLASSIFICATION = "PII";
public static final String METRIC_CLASSIFICATION = "Metric";
public static final String ETL_CLASSIFICATION = "ETL";
public static final String JDBC_CLASSIFICATION = "JdbcAccess";
public static final String LOGDATA_CLASSIFICATION = "Log Data";
@Inject
protected AtlasTypeRegistry atlasTypeRegistry;
protected AtlasTypeRegistry typeRegistry;
@Inject
protected AtlasTypeDefStore atlasTypeDefStore;
protected AtlasTypeDefStore typeDefStore;
@Inject
protected AtlasEntityStore atlasEntityStore;
protected AtlasEntityStore entityStore;
private boolean baseLoaded = false;
......@@ -67,9 +75,8 @@ public abstract class BasicTestSetup {
}
private void loadBaseModels() {
// Load all base models
try {
loadModelFromJson("0000-Area0/0010-base_model.json", atlasTypeDefStore, atlasTypeRegistry);
loadModelFromJson("0000-Area0/0010-base_model.json", typeDefStore, typeRegistry);
baseLoaded = true;
} catch (IOException | AtlasBaseException e) {
fail("Base model setup is required for test to run");
......@@ -82,7 +89,7 @@ public abstract class BasicTestSetup {
}
try {
loadModelFromJson("1000-Hadoop/1030-hive_model.json", atlasTypeDefStore, atlasTypeRegistry);
loadModelFromJson("1000-Hadoop/1030-hive_model.json", typeDefStore, typeRegistry);
} catch (IOException | AtlasBaseException e) {
fail("Hive model setup is required for test to run");
}
......@@ -90,7 +97,7 @@ public abstract class BasicTestSetup {
AtlasEntity.AtlasEntitiesWithExtInfo hiveTestEntities = hiveTestEntities();
try {
atlasEntityStore.createOrUpdate(new AtlasEntityStream(hiveTestEntities), false);
entityStore.createOrUpdate(new AtlasEntityStream(hiveTestEntities), false);
} catch (AtlasBaseException e) {
fail("Hive instance setup is needed for test to run");
}
......@@ -105,7 +112,7 @@ public abstract class BasicTestSetup {
AtlasTypesDef employeeTypes = TestUtilsV2.defineDeptEmployeeTypes();
try {
atlasTypeDefStore.createTypesDef(employeeTypes);
typeDefStore.createTypesDef(employeeTypes);
} catch (AtlasBaseException e) {
fail("Employee Type setup is required");
}
......@@ -114,7 +121,7 @@ public abstract class BasicTestSetup {
AtlasEntity.AtlasEntitiesWithExtInfo deptEg2 = TestUtilsV2.createDeptEg2();
try {
atlasEntityStore.createOrUpdate(new AtlasEntityStream(deptEg2), false);
entityStore.createOrUpdate(new AtlasEntityStream(deptEg2), false);
} catch (AtlasBaseException e) {
fail("Employee entity setup should've passed");
}
......@@ -123,8 +130,9 @@ public abstract class BasicTestSetup {
public AtlasEntity.AtlasEntitiesWithExtInfo hiveTestEntities() {
List<AtlasEntity> entities = new ArrayList<>();
AtlasEntity salesDB = database("Sales", "Sales Database", "John ETL", "hdfs://host:8000/apps/warehouse/sales");
createClassificationTypes();
AtlasEntity salesDB = database("Sales", "Sales Database", "John ETL", "hdfs://host:8000/apps/warehouse/sales");
entities.add(salesDB);
AtlasEntity sd =
......@@ -143,8 +151,10 @@ public abstract class BasicTestSetup {
entities.add(salesFact);
List<AtlasEntity> logFactColumns = ImmutableList
.of(column("time_id", "int", "time id"), column("app_id", "int", "app id"),
column("machine_id", "int", "machine id"), column("log", "string", "log data", "Log Data"));
.of(column("time_id", "int", "time id"),
column("app_id", "int", "app id"),
column("machine_id", "int", "machine id"),
column("log", "string", "log data", "Log Data"));
entities.addAll(logFactColumns);
List<AtlasEntity> timeDimColumns = ImmutableList
......@@ -238,24 +248,46 @@ public abstract class BasicTestSetup {
ImmutableList.of(loggingFactMonthly), "create table as select ", "plan", "id", "graph", "ETL");
entities.add(loadLogsMonthly);
AtlasEntity partition = partition(new ArrayList() {{
add("2015-01-01");
}}, salesFactDaily);
entities.add(partition);
AtlasEntity datasetSubType = datasetSubType("dataSetSubTypeInst1", "testOwner");
entities.add(datasetSubType);
return new AtlasEntity.AtlasEntitiesWithExtInfo(entities);
}
protected void createClassificationTypes() {
List<AtlasClassificationDef> cds = Arrays.asList(new AtlasClassificationDef(DIMENSION_CLASSIFICATION, "Dimension Classification", "1.0"),
new AtlasClassificationDef(FACT_CLASSIFICATION, "Fact Classification", "1.0"),
new AtlasClassificationDef(PII_CLASSIFICATION, "PII Classification", "1.0"),
new AtlasClassificationDef(METRIC_CLASSIFICATION, "Metric Classification", "1.0"),
new AtlasClassificationDef(ETL_CLASSIFICATION, "ETL Classification", "1.0"),
new AtlasClassificationDef(JDBC_CLASSIFICATION, "JdbcAccess Classification", "1.0"),
new AtlasClassificationDef(LOGDATA_CLASSIFICATION, "LogData Classification", "1.0"));
AtlasTypesDef tds = new AtlasTypesDef(Collections.<AtlasEnumDef>emptyList(),
Collections.<AtlasStructDef>emptyList(),
cds,
Collections.<AtlasEntityDef>emptyList());
createUpdateClassificationDef(tds);
}
private void createUpdateClassificationDef(AtlasTypesDef td) {
try {
typeDefStore.createTypesDef(td);
}
catch(Exception e) {
fail("Error creating classifications definitions.");
}
}
AtlasEntity database(String name, String description, String owner, String locationUri, String... traitNames) {
AtlasEntity database = new AtlasEntity(DATABASE_TYPE);
database.setAttribute("name", name);
database.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, "qualified:" + name);
database.setAttribute("description", description);
database.setAttribute("owner", owner);
database.setAttribute("locationUri", locationUri);
database.setAttribute("createTime", System.currentTimeMillis());
database.setAttribute("clusterName", "cl1");
database.setClassifications(Stream.of(traitNames).map(AtlasClassification::new).collect(Collectors.toList()));
return database;
......@@ -264,10 +296,11 @@ public abstract class BasicTestSetup {
protected AtlasEntity storageDescriptor(String location, String inputFormat, String outputFormat, boolean compressed, List<AtlasEntity> columns) {
AtlasEntity storageDescriptor = new AtlasEntity(STORAGE_DESC_TYPE);
storageDescriptor.setAttribute("location", location);
storageDescriptor.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, "qualified:" + location);
storageDescriptor.setAttribute("inputFormat", inputFormat);
storageDescriptor.setAttribute("outputFormat", outputFormat);
storageDescriptor.setAttribute("compressed", compressed);
storageDescriptor.setAttribute("cols", columns);
storageDescriptor.setAttribute("cols", getAtlasObjectIds(columns));
return storageDescriptor;
}
......@@ -275,7 +308,8 @@ public abstract class BasicTestSetup {
protected AtlasEntity column(String name, String dataType, String comment, String... traitNames) {
AtlasEntity column = new AtlasEntity(COLUMN_TYPE);
column.setAttribute("name", name);
column.setAttribute("dataType", dataType);
column.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, "qualified:" + name);
column.setAttribute("type", dataType);
column.setAttribute("comment", comment);
column.setClassifications(Stream.of(traitNames).map(AtlasClassification::new).collect(Collectors.toList()));
......@@ -295,27 +329,42 @@ public abstract class BasicTestSetup {
table.setAttribute("lastAccessTime", System.currentTimeMillis());
table.setAttribute("retention", System.currentTimeMillis());
table.setAttribute("db", db);
// todo - uncomment this, something is broken
table.setAttribute("sd", sd);
table.setAttribute("columns", columns);
table.setAttribute("db", getAtlasObjectId(db));
table.setAttribute("sd", getAtlasObjectId(sd));
table.setAttribute("columns", getAtlasObjectIds(columns));
table.setClassifications(Stream.of(traitNames).map(AtlasClassification::new).collect(Collectors.toList()));
return table;
}
protected AtlasEntity loadProcess(String name, String description, String user, List<AtlasEntity> inputTables, List<AtlasEntity> outputTables,
private List<AtlasObjectId> getAtlasObjectIds(List<AtlasEntity> columns) {
List<AtlasObjectId> objIds = new ArrayList<>();
for (AtlasEntity e : columns) {
AtlasObjectId oid = getAtlasObjectId(e);
objIds.add(oid);
}
return objIds;
}
private AtlasObjectId getAtlasObjectId(AtlasEntity e) {
return new AtlasObjectId(e.getGuid(), e.getTypeName());
}
protected AtlasEntity loadProcess(String name, String description, String user,
List<AtlasEntity> inputTables, List<AtlasEntity> outputTables,
String queryText, String queryPlan, String queryId, String queryGraph, String... traitNames) {
AtlasEntity process = new AtlasEntity(HIVE_PROCESS_TYPE);
process.setAttribute("name", name);
process.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, name);
process.setAttribute("description", description);
process.setAttribute("user", user);
process.setAttribute("userName", user);
process.setAttribute("startTime", System.currentTimeMillis());
process.setAttribute("endTime", System.currentTimeMillis() + 10000);
process.setAttribute("inputs", inputTables);
process.setAttribute("outputs", outputTables);
process.setAttribute("operationType", "load");
process.setAttribute("inputs", getAtlasObjectIds(inputTables));
process.setAttribute("outputs", getAtlasObjectIds(outputTables));
process.setAttribute("queryText", queryText);
process.setAttribute("queryPlan", queryPlan);
......@@ -331,22 +380,22 @@ public abstract class BasicTestSetup {
AtlasEntity view = new AtlasEntity(VIEW_TYPE);
view.setAttribute("name", name);
view.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, name);
view.setAttribute("db", dbId);
view.setAttribute("inputTables", inputTables);
view.setAttribute("userName", "testUser");
view.setAttribute("startTime", System.currentTimeMillis());
view.setAttribute("endTime", System.currentTimeMillis() + 10000);
view.setAttribute("operationType", "view");
view.setAttribute("query", "create table as select");
view.setAttribute("queryText", "create table as select");
view.setAttribute("queryPlan", "viewPlan");
view.setAttribute("queryId", "view1");
view.setAttribute("db", getAtlasObjectId(dbId));
view.setAttribute("inputs", getAtlasObjectIds(inputTables));
view.setClassifications(Stream.of(traitNames).map(AtlasClassification::new).collect(Collectors.toList()));
return view;
}
AtlasEntity partition(List<String> values, AtlasEntity table, String... traitNames) {
AtlasEntity partition = new AtlasEntity(PARTITION_TYPE);
partition.setAttribute("values", values);
partition.setAttribute("table", table);
partition.setClassifications(Stream.of(traitNames).map(AtlasClassification::new).collect(Collectors.toList()));
return partition;
}
AtlasEntity datasetSubType(final String name, String owner) {
AtlasEntity datasetSubType = new AtlasEntity(DATASET_SUBTYPE);
datasetSubType.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, name);
......
......@@ -30,8 +30,7 @@ import org.testng.annotations.Test;
import javax.inject.Inject;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.*;
@Guice(modules = TestModules.TestOnlyModule.class)
public class DSLQueriesTest extends BasicTestSetup {
......@@ -50,16 +49,14 @@ public class DSLQueriesTest extends BasicTestSetup {
}
@DataProvider(name = "comparisonQueriesProvider")
private Object[][] createComparisonQueries() {
//create queries the exercise the comparison logic for
//all of the different supported data types
private Object[][] comparisonQueriesProvider() {
return new Object[][] {
{"Person where (birthday < \"1950-01-01T02:35:58.440Z\" )", 0},
{"Person where (birthday > \"1975-01-01T02:35:58.440Z\" )", 2},
{"Person where (birthday >= \"1975-01-01T02:35:58.440Z\" )", 2},
{"Person where (birthday <= \"1950-01-01T02:35:58.440Z\" )", 0},
{"Person where (birthday = \"1975-01-01T02:35:58.440Z\" )", 0},
{"Person where (birthday != \"1975-01-01T02:35:58.440Z\" )", 4},
{"Person where (birthday != \"1975-01-01T02:35:58.440Z\" )", 0},
{"Person where (hasPets = true)", 2},
{"Person where (hasPets = false)", 2},
......@@ -72,7 +69,7 @@ public class DSLQueriesTest extends BasicTestSetup {
{"Person where (numberOfCars < 2)", 3},
{"Person where (numberOfCars <= 2)", 4},
{"Person where (numberOfCars = 2)", 1},
{"Person where (numberOfCars != 2)", 3},
{"Person where (numberOfCars != 2)", 0},
{"Person where (houseNumber > 0)", 2},
{"Person where (houseNumber > 17)", 1},
......@@ -80,7 +77,7 @@ public class DSLQueriesTest extends BasicTestSetup {
{"Person where (houseNumber < 153)", 3},
{"Person where (houseNumber <= 153)", 4},
{"Person where (houseNumber = 17)", 1},
{"Person where (houseNumber != 17)", 3},
{"Person where (houseNumber != 17)", 0},
{"Person where (carMileage > 0)", 2},
{"Person where (carMileage > 13)", 1},
......@@ -88,23 +85,7 @@ public class DSLQueriesTest extends BasicTestSetup {
{"Person where (carMileage < 13364)", 3},
{"Person where (carMileage <= 13364)", 4},
{"Person where (carMileage = 13)", 1},
{"Person where (carMileage != 13)", 3},
{"Person where (shares > 0)", 2},
{"Person where (shares > 13)", 2},
{"Person where (shares >= 16000)", 1},
{"Person where (shares < 13364)", 2},
{"Person where (shares <= 15000)", 3},
{"Person where (shares = 15000)", 1},
{"Person where (shares != 1)", 4},
{"Person where (salary > 0)", 2},
{"Person where (salary > 100000)", 2},
{"Person where (salary >= 200000)", 1},
{"Person where (salary < 13364)", 2},
{"Person where (salary <= 150000)", 3},
{"Person where (salary = 12334)", 0},
{"Person where (salary != 12344)", 4},
{"Person where (carMileage != 13)", 0},
{"Person where (age > 36)", 1},
{"Person where (age > 49)", 1},
......@@ -112,149 +93,85 @@ public class DSLQueriesTest extends BasicTestSetup {
{"Person where (age < 50)", 3},
{"Person where (age <= 35)", 2},
{"Person where (age = 35)", 0},
{"Person where (age != 35)", 4}
{"Person where (age != 35)", 0}
};
}
@Test(dataProvider = "comparisonQueriesProvider")
public void testComparisonQueries(String query, int expected) throws AtlasBaseException {
public void comparison(String query, int expected) throws AtlasBaseException {
AtlasSearchResult searchResult = discoveryService.searchUsingDslQuery(query, 25, 0);
assertNotNull(searchResult.getEntities());
assertEquals(searchResult.getEntities().size(), expected);
assertSearchResult(searchResult, expected);
}
@DataProvider(name = "dslQueriesProvider")
private Object[][] createDSLQueries() {
@DataProvider(name = "basicProvider")
private Object[][] basicQueries() {
return new Object[][]{
{"hive_db as inst where inst.name=\"Reporting\" select inst as id, inst.name", 1},
{"from hive_db as h select h as id", 3},
{"from hive_db", 3},
{"hive_db", 3},
{"hive_db where hive_db.name=\"Reporting\"", 1},
{"hive_db hive_db.name = \"Reporting\"", 1},
{"hive_db hive_db.name = \"Reporting\"", 3},
{"hive_db where hive_db.name=\"Reporting\" select name, owner", 1},
{"hive_db has name", 3},
{"hive_db, hive_table", 10},
{"View is JdbcAccess", 2},
{"hive_db as db1, hive_table where db1.name = \"Reporting\"", 0}, //Not working - ATLAS-145
// - Final working query -> discoveryService.searchByGremlin("L:{_var_0 = [] as Set;g.V().has(\"__typeName\", \"hive_db\").fill(_var_0);g.V().has(\"__superTypeNames\", \"hive_db\").fill(_var_0);_var_0._().as(\"db1\").in(\"__hive_table.db\").back(\"db1\").and(_().has(\"hive_db.name\", T.eq, \"Reporting\")).toList()}")
/*
{"hive_db, hive_process has name"}, //Invalid query
{"hive_db where hive_db.name=\"Reporting\" and hive_db.createTime < " + System.currentTimeMillis()}
*/
{"from hive_table", 10},
{"hive_table", 10},
{"hive_table isa Dimension", 3},
{"hive_column where hive_column isa PII", 8},
{"View is Dimension" , 2},
// {"hive_column where hive_column isa PII select hive_column.name", 6}, //Not working - ATLAS-175
{"hive_column select hive_column.name", 37},
{"hive_column select name",37},
{"hive_column where hive_column.name=\"customer_id\"", 6},
{"hive_column where hive_column isa PII", 4},
{"hive_column where hive_column isa PII select hive_column.name", 4},
{"hive_column select hive_column.name", 17},
{"hive_column select name", 17},
{"hive_column where hive_column.name=\"customer_id\"", 2},
{"from hive_table select hive_table.name", 10},
{"hive_db where (name = \"Reporting\")", 1},
{"hive_db where (name = \"Reporting\") select name as _col_0, owner as _col_1", 1},
{"hive_db where hive_db is JdbcAccess", 0}, //Not supposed to work
{"hive_db hive_table", 10},
{"hive_db where hive_db is JdbcAccess", 0},
{"hive_db where hive_db has name", 3},
{"hive_db as db1 hive_table where (db1.name = \"Reporting\")", 0}, //Not working -> ATLAS-145
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 ", 1},
{"hive_db as db1 hive_table where (db1.name = \"Reporting\")", 0},
{"hive_table where (name = \"sales_fact\" and createTime > \"2014-01-01\" ) select name as _col_0, createTime as _col_1 ", 1},
{"hive_table where (name = \"sales_fact\" and createTime >= \"2014-12-11T02:35:58.440Z\" ) select name as _col_0, createTime as _col_1 ", 1},
/*
todo: does not work - ATLAS-146
{"hive_db where (name = \"Reporting\") and ((createTime + 1) > 0)"},
{"hive_db as db1 hive_table as tab where ((db1.createTime + 1) > 0) and (db1.name = \"Reporting\") select db1.name
as dbName, tab.name as tabName"},
{"hive_db as db1 hive_table as tab where ((db1.createTime + 1) > 0) or (db1.name = \"Reporting\") select db1.name
as dbName, tab.name as tabName"},
{"hive_db as db1 hive_table as tab where ((db1.createTime + 1) > 0) and (db1.name = \"Reporting\") or db1 has owner
select db1.name as dbName, tab.name as tabName"},
{"hive_db as db1 hive_table as tab where ((db1.createTime + 1) > 0) and (db1.name = \"Reporting\") or db1 has owner
select db1.name as dbName, tab.name as tabName"},
*/
// trait searches
{"Dimension", 5},
{"JdbcAccess", 2},
{"ETL", 5},
{"Metric", 9},
{"PII", 8},
{"`Log Data`", 4},
// Not sure what the expected rows should be, but since we didn't assign or do anything with the created
// I assume it'll be zero
{"Metric", 5},
{"PII", 4},
{"`Log Data`", 3},
{"`isa`", 0},
/* Lineage queries are fired through ClosureQuery and are tested through HiveLineageJerseyResourceIt in webapp module.
Commenting out the below queries since DSL to Gremlin parsing/translation fails with lineage queries when there are array types
used within loop expressions which is the case with DataSet.inputs and outputs.`
// Lineage
{"Table LoadProcess outputTable"}, {"Table loop (LoadProcess outputTable)"},
{"Table as _loop0 loop (LoadProcess outputTable) withPath"},
{"Table as src loop (LoadProcess outputTable) as dest select src.name as srcTable, dest.name as "
+ "destTable withPath"},
*/
// {"hive_table as t, sd, hive_column as c where t.name=\"sales_fact\" select c.name as colName, c.dataType as "
// + "colType", 0}, //Not working - ATLAS-145 and ATLAS-166
{"hive_table as t, sd, hive_column as c where t.name=\"sales_fact\" select c.name as colName, c.dataType as colType", 0},
{"hive_table where name='sales_fact', db where name='Sales'", 1},
{"hive_table where name='sales_fact', db where name='Reporting'", 0},
{"hive_partition as p where values = ['2015-01-01']", 1},
// {"StorageDesc select cols", 6} //Not working since loading of lists needs to be fixed yet
//check supertypeNames
{"DataSet where name='sales_fact'", 1},
{"Asset where name='sales_fact'", 1}
};
}
@Test(dataProvider = "dslQueriesProvider")
public void testBasicDSL(String query, int expected) throws AtlasBaseException {
@Test(dataProvider = "basicProvider")
public void basic(String query, int expected) throws AtlasBaseException {
AtlasSearchResult searchResult = discoveryService.searchUsingDslQuery(query, 25, 0);
assertNotNull(searchResult.getEntities());
assertEquals(searchResult.getEntities().size(), expected);
assertSearchResult(searchResult, expected);
}
@DataProvider(name = "dslExplicitLimitQueriesProvider")
private Object[][] createDSLQueriesWithExplicitLimit() {
@DataProvider(name = "limitProvider")
private Object[][] limitQueries() {
return new Object[][]{
{"hive_column", 37, 40, 0},//with higher limit all rows returned
{"hive_column limit 10", 10, 50, 0},//lower limit in query
{"hive_column select hive_column.name limit 10", 5, 5, 0},//lower limit in query param
{"hive_column select hive_column.name withPath", 20, 20, 0},//limit only in params
//with offset, only remaining rows returned
{"hive_column select hive_column.name limit 40 withPath", 17, 40, 20},
//with higher offset, no rows returned
{"hive_column select hive_column.name limit 40 withPath", 0, 40, 40},
//offset used from query
{"hive_column select hive_column.name limit 40 offset 10", 27, 40, 0},
//offsets in query and parameter added up
{"hive_column select hive_column.name limit 40 offset 10", 17, 40, 10},
//works with where clause
{"hive_column", 17, 40, 0},
{"hive_column limit 10", 10, 50, 0},
{"hive_column select hive_column.name limit 10", 10, 5, 0},
{"hive_column select hive_column.name limit 40 offset 10", 7, 40, 0},
{"hive_db where name = 'Reporting' limit 10 offset 0", 1, 40, 0},
//works with joins
{"hive_db, hive_table where db.name = 'Reporting' limit 10", 1, 1, 0},
{"hive_column limit 25", 5, 10, 20}, //last page should return records limited by limit in query
{"hive_column limit 25", 0, 10, 30}, //offset > limit returns 0 rows
{"hive_table where db.name = 'Reporting' limit 10", 4, 1, 0},
};
}
@Test(dataProvider = "dslExplicitLimitQueriesProvider")
public void testExplicitDSL(String query, int expected, int limit, int offset) throws AtlasBaseException {
@Test(dataProvider = "limitProvider")
public void limit(String query, int expected, int limit, int offset) throws AtlasBaseException {
AtlasSearchResult searchResult = discoveryService.searchUsingDslQuery(query, limit, offset);
assertNotNull(searchResult.getEntities());
assertEquals(searchResult.getEntities().size(), expected);
assertSearchResult(searchResult, expected);
}
@DataProvider(name = "dslLimitQueriesProvider")
private Object[][] createDSLQueriesWithLimit() {
@DataProvider(name = "syntaxVerifierProvider")
private Object[][] syntaxVerifierQueries() {
return new Object[][]{
{"hive_column limit 10 ", 10},
{"hive_column select hive_column.name limit 10 ", 10},
{"hive_column select hive_column.name withPath", 37},
{"hive_column select hive_column.name limit 10 withPath", 10},
{"from hive_db", 3},
{"from hive_db limit 2", 2},
{"from hive_db limit 2 offset 0", 2},
......@@ -266,23 +183,12 @@ public class DSLQueriesTest extends BasicTestSetup {
{"hive_db where hive_db.name=\"Reporting\" or hive_db.name=\"Sales\" or hive_db.name=\"Logging\" limit 1 offset 2", 1},
{"hive_db where hive_db.name=\"Reporting\" or hive_db.name=\"Sales\" or hive_db.name=\"Logging\" limit 2 offset 1", 2},
{"hive_db where hive_db.name=\"Reporting\" limit 10 ", 1},
{"hive_db hive_db.name = \"Reporting\"", 1},
{"hive_db where hive_db.name=\"Reporting\" select name, owner", 1},
{"hive_db has name", 3},
{"hive_db has name limit 2 offset 0", 2},
{"hive_db has name limit 2 offset 1", 2},
{"hive_db has name limit 10 offset 1", 2},
{"hive_db has name limit 10 offset 0", 3},
{"hive_db, hive_table", 10},
{"hive_db, hive_table limit 5", 5},
{"hive_db, hive_table limit 5 offset 0", 5},
{"hive_db, hive_table limit 5 offset 5", 5},
{"View is JdbcAccess", 2},
{"View is JdbcAccess limit 1", 1},
{"View is JdbcAccess limit 2 offset 1", 1},
{"hive_db as db1, hive_table where db1.name = \"Reporting\"", 0}, //Not working - ATLAS-145
{"from hive_table", 10},
{"from hive_table limit 5", 5},
......@@ -297,30 +203,25 @@ public class DSLQueriesTest extends BasicTestSetup {
{"hive_table isa Dimension limit 2 offset 0", 2},
{"hive_table isa Dimension limit 2 offset 1", 2},
{"hive_table isa Dimension limit 3 offset 1", 2},
{"hive_table where db.name='Sales' and db.clusterName='cl1'", 4},
{"hive_column where hive_column isa PII", 8},
{"hive_column where hive_column isa PII limit 5", 5},
{"hive_column where hive_column isa PII limit 5 offset 1", 5},
{"hive_column where hive_column isa PII limit 5 offset 5", 3},
{"hive_column where hive_column isa PII", 4},
{"hive_column where hive_column isa PII limit 5", 4},
{"hive_column where hive_column isa PII limit 5 offset 1", 3},
{"hive_column where hive_column isa PII limit 5 offset 5", 0},
{"View is Dimension" , 2},
{"View is Dimension limit 1" , 1},
{"View is Dimension limit 1 offset 1" , 1},
{"View is Dimension limit 10 offset 1" , 1},
{"hive_column select hive_column.name", 37},
{"hive_column select hive_column.name", 17},
{"hive_column select hive_column.name limit 5", 5},
{"hive_column select hive_column.name limit 5 offset 36", 1},
{"hive_column select hive_column.name limit 5 offset 36", 0},
{"hive_column select name", 37},
{"hive_column select name", 17},
{"hive_column select name limit 5", 5},
{"hive_column select name limit 5 offset 36 ", 1},
{"hive_column select name limit 5 offset 36 ", 0},
{"hive_column where hive_column.name=\"customer_id\"", 6},
{"hive_column where hive_column.name=\"customer_id\"", 2},
{"hive_column where hive_column.name=\"customer_id\" limit 2", 2},
{"hive_column where hive_column.name=\"customer_id\" limit 2 offset 1", 2},
{"hive_column where hive_column.name=\"customer_id\" limit 10 offset 3", 3},
{"hive_column where hive_column.name=\"customer_id\" limit 2 offset 1", 1},
{"hive_column where hive_column.name=\"customer_id\" limit 10 offset 3", 0},
{"from hive_table select hive_table.name", 10},
{"from hive_table select hive_table.name limit 5", 5},
......@@ -331,19 +232,12 @@ public class DSLQueriesTest extends BasicTestSetup {
{"hive_db where (name = \"Reporting\") select name as _col_0, owner as _col_1", 1},
{"hive_db where (name = \"Reporting\") select name as _col_0, owner as _col_1 limit 10", 1},
{"hive_db where hive_db is JdbcAccess", 0}, //Not supposed to work
{"hive_db hive_table", 10},
{"hive_db hive_table limit 5", 5},
{"hive_db hive_table limit 5 offset 5", 5},
{"hive_db where hive_db has name", 3},
{"hive_db where hive_db has name limit 5", 3},
{"hive_db where hive_db has name limit 2 offset 0", 2},
{"hive_db where hive_db has name limit 2 offset 1", 2},
{"hive_db as db1 hive_table where (db1.name = \"Reporting\")", 0}, //Not working -> ATLAS-145
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 ", 1},
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 limit 10", 1},
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 limit 10 offset 1", 0},
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 limit 10 offset 0", 1},
{"hive_db as db1 hive_table where (db1.name = \"Reporting\")", 0},
{"hive_table where (name = \"sales_fact\" and createTime > \"2014-01-01\" ) select name as _col_0, createTime as _col_1 ", 1},
{"hive_table where (name = \"sales_fact\" and createTime > \"2014-01-01\" ) select name as _col_0, createTime as _col_1 limit 10 ", 1},
......@@ -356,93 +250,39 @@ public class DSLQueriesTest extends BasicTestSetup {
{"hive_table where (name = \"sales_fact\" and createTime >= \"2014-12-11T02:35:58.440Z\" ) select name as _col_0, createTime as _col_1 limit 10", 1},
{"hive_table where (name = \"sales_fact\" and createTime >= \"2014-12-11T02:35:58.440Z\" ) select name as _col_0, createTime as _col_1 limit 0 offset 1", 0},
// trait searches
{"Dimension", 5},
{"Dimension limit 2", 2},
{"Dimension limit 2 offset 1", 2},
{"Dimension limit 5 offset 4", 1},
{"JdbcAccess", 2},
{"JdbcAccess limit 5 offset 0", 2},
{"JdbcAccess limit 2 offset 1", 1},
{"JdbcAccess limit 1", 1},
{"ETL", 5},
{"ETL limit 2", 2},
{"ETL limit 1", 1},
{"ETL limit 1 offset 0", 1},
{"ETL limit 2 offset 1", 2},
{"Metric", 9},
{"Metric limit 10", 9},
{"Metric limit 2", 2},
{"Metric limit 10 offset 1", 8},
{"PII", 8},
{"PII limit 10", 8},
{"PII limit 2", 2},
{"PII limit 10 offset 1", 7},
{"`Log Data`", 4},
{"`Log Data` limit 3", 3},
{"`Log Data` limit 10 offset 2", 2},
{"hive_table where name='sales_fact', db where name='Sales'", 1},
{"hive_table where name='sales_fact', db where name='Sales' limit 10", 1},
{"hive_table where name='sales_fact', db where name='Sales' limit 10 offset 1", 0},
{"hive_table where name='sales_fact', db where name='Reporting'", 0},
{"hive_table where name='sales_fact', db where name='Reporting' limit 10", 0},
{"hive_table where name='sales_fact', db where name='Reporting' limit 10 offset 1", 0},
{"hive_partition as p where values = ['2015-01-01']", 1},
{"hive_partition as p where values = ['2015-01-01'] limit 10", 1},
{"hive_partition as p where values = ['2015-01-01'] limit 10 offset 1", 0},
};
}
@Test(dataProvider = "dslLimitQueriesProvider")
public void testDSLLimitQueries(String query, int expected) throws AtlasBaseException {
@Test(dataProvider = "syntaxVerifierProvider")
public void syntax(String query, int expected) throws AtlasBaseException {
AtlasSearchResult searchResult = discoveryService.searchUsingDslQuery(query, 25, 0);
assertNotNull(searchResult.getEntities());
assertEquals(searchResult.getEntities().size(), expected);
assertSearchResult(searchResult, expected);
}
@DataProvider(name = "dslOrderByQueriesProvider")
private Object[][] createDSLQueriesWithOrderBy() {
@DataProvider(name = "orderByProvider")
private Object[][] orderByQueries() {
return new Object[][]{
//test with alias
// {"from hive_db select hive_db.name as 'o' orderby o limit 3", 3, "name", isAscending},
{"from hive_db as h orderby h.owner limit 3", 3, "owner", true},
{"hive_column as c select c.name orderby hive_column.name ", 37, "c.name", true},
{"hive_column as c select c.name orderby hive_column.name ", 17, "c.name", true},
{"hive_column as c select c.name orderby hive_column.name limit 5", 5, "c.name", true},
{"hive_column as c select c.name orderby hive_column.name desc limit 5", 5, "c.name", false},
{"from hive_db orderby hive_db.owner limit 3", 3, "owner", true},
{"hive_column select hive_column.name orderby hive_column.name ", 37, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name ", 17, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name limit 5", 5, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name desc limit 5", 5, "hive_column.name", false},
{"from hive_db orderby owner limit 3", 3, "owner", true},
{"hive_column select hive_column.name orderby name ", 37, "hive_column.name", true},
{"hive_column select hive_column.name orderby name ", 17, "hive_column.name", true},
{"hive_column select hive_column.name orderby name limit 5", 5, "hive_column.name", true},
{"hive_column select hive_column.name orderby name desc limit 5", 5, "hive_column.name", false},
//Not working, the problem is in server code not figuring out how to sort. not sure if it is valid use case.
// {"hive_db hive_table orderby 'hive_db.owner'", 10, "owner", isAscending},
// {"hive_db hive_table orderby 'hive_db.owner' limit 5", 5, "owner", isAscending},
// {"hive_db hive_table orderby 'hive_db.owner' limit 5 offset 5", 3, "owner", isAscending},
{"hive_db select hive_db.description orderby hive_db.description limit 10 withPath", 3, "hive_db.description", true},
{"hive_db select hive_db.description orderby hive_db.description desc limit 10 withPath", 3, "hive_db.description", false},
{"hive_column select hive_column.name orderby hive_column.name limit 10 withPath", 10, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name asc limit 10 withPath", 10, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name desc limit 10 withPath", 10, "hive_column.name", false},
{"from hive_db orderby hive_db.owner limit 3", 3, "owner", true},
{"hive_db where hive_db.name=\"Reporting\" orderby 'owner'", 1, "owner", true},
......@@ -460,30 +300,19 @@ public class DSLQueriesTest extends BasicTestSetup {
{"hive_table orderby hive_table.owner limit 8 offset 0", 8, "owner", true},
{"hive_table orderby hive_table.owner desc limit 8 offset 0", 8, "owner", false},
//Not working because of existing bug Atlas-175
// {"hive_table isa Dimension orderby hive_table.owner", 3, "hive_table.owner", isAscending},//order not working
// {"hive_table isa Dimension orderby hive_table.owner limit 3", 3, "hive_table.owner", isAscending},
// {"hive_table isa Dimension orderby hive_table.owner limit 3 offset 0", 3, "hive_table.owner", isAscending},
// {"hive_table isa Dimension orderby hive_table.owner desc limit 3 offset 0", 3, "hive_table.owner", !isAscending},
//
// {"hive_column where hive_column isa PII orderby hive_column.name", 6, "hive_column.name", isAscending},
// {"hive_column where hive_column isa PII orderby hive_column.name limit 5", 5, "hive_column.name", isAscending},
// {"hive_column where hive_column isa PII orderby hive_column.name limit 5 offset 1", 5, "hive_column.name", isAscending},
// {"hive_column where hive_column isa PII orderby hive_column.name desc limit 5 offset 1", 5, "hive_column.name", !isAscending},
{"hive_column select hive_column.name orderby hive_column.name ", 37, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name ", 17, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name limit 5", 5, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name desc limit 5", 5, "hive_column.name", false},
{"hive_column select hive_column.name orderby hive_column.name limit 5 offset 28", 5, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name limit 5 offset 2", 5, "hive_column.name", true},
{"hive_column select name orderby hive_column.name", 37, "name", true},
{"hive_column select name orderby hive_column.name", 17, "name", true},
{"hive_column select name orderby hive_column.name limit 5", 5, "name", true},
{"hive_column select name orderby hive_column.name desc", 37, "name", false},
{"hive_column select name orderby hive_column.name desc", 17, "name", false},
{"hive_column where hive_column.name=\"customer_id\" orderby hive_column.name", 6, "name", true},
{"hive_column where hive_column.name=\"customer_id\" orderby hive_column.name", 2, "name", true},
{"hive_column where hive_column.name=\"customer_id\" orderby hive_column.name limit 2", 2, "name", true},
{"hive_column where hive_column.name=\"customer_id\" orderby hive_column.name limit 2 offset 1", 2, "name", true},
{"hive_column where hive_column.name=\"customer_id\" orderby hive_column.name limit 2 offset 1", 1, "name", true},
{"from hive_table select owner orderby hive_table.owner",10, "owner", true},
{"from hive_table select owner orderby hive_table.owner limit 5", 5, "owner", true},
......@@ -497,12 +326,6 @@ public class DSLQueriesTest extends BasicTestSetup {
{"hive_db where hive_db has name orderby hive_db.owner limit 2 offset 0", 2, "owner", true},
{"hive_db where hive_db has name orderby hive_db.owner limit 2 offset 1", 2, "owner", true},
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 orderby '_col_1'", 1, "_col_1", true},
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 orderby '_col_1' limit 10", 1, "_col_1", true},
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 orderby '_col_1' limit 10 offset 1", 0, "_col_1", true},
{"hive_db where (name = \"Reporting\") select name as _col_0, (createTime + 1) as _col_1 orderby '_col_1' limit 10 offset 0", 1, "_col_1", true},
{"hive_table where (name = \"sales_fact\" and createTime > \"2014-01-01\" ) select name as _col_0, createTime as _col_1 orderby '_col_1' ", 1, "_col_1", true},
{"hive_table where (name = \"sales_fact\" and createTime > \"2014-01-01\" ) select name as _col_0, createTime as _col_1 orderby '_col_1' limit 10 ", 1, "_col_1", true},
{"hive_table where (name = \"sales_fact\" and createTime > \"2014-01-01\" ) select name as _col_0, createTime as _col_1 orderby '_col_1' limit 10 offset 0", 1, "_col_1", true},
......@@ -513,23 +336,17 @@ public class DSLQueriesTest extends BasicTestSetup {
{"hive_table where (name = \"sales_fact\" and createTime >= \"2014-12-11T02:35:58.440Z\" ) select name as _col_0, createTime as _col_1 orderby '_col_0' limit 10 offset 1", 0, "_col_0", true},
{"hive_table where (name = \"sales_fact\" and createTime >= \"2014-12-11T02:35:58.440Z\" ) select name as _col_0, createTime as _col_1 orderby '_col_0' limit 10", 1, "_col_0", true},
{"hive_table where (name = \"sales_fact\" and createTime >= \"2014-12-11T02:35:58.440Z\" ) select name as _col_0, createTime as _col_1 orderby '_col_0' limit 0 offset 1", 0, "_col_0", true},
{"hive_column select hive_column.name orderby hive_column.name limit 10 withPath", 10, "hive_column.name", true},
{"hive_column select hive_column.name orderby hive_column.name limit 10 withPath", 10, "hive_column.name", true},
{"hive_table orderby 'hive_table.owner_notdefined'", 10, null, true},
};
}
@Test(dataProvider = "dslOrderByQueriesProvider")
public void testOrderByDSL(String query, int expected, String orderBy, boolean ascending) throws AtlasBaseException {
@Test(dataProvider = "orderByProvider")
public void orderBy(String query, int expected, String orderBy, boolean ascending) throws AtlasBaseException {
AtlasSearchResult searchResult = discoveryService.searchUsingDslQuery(query, 25, 0);
assertNotNull(searchResult.getEntities());
assertEquals(searchResult.getEntities().size(), expected);
// TODO: Implement order checking here
assertSearchResult(searchResult, expected);
}
@DataProvider(name = "dslLikeQueriesProvider")
private Object[][] createDslLikeQueries() {
@DataProvider(name = "likeQueriesProvider")
private Object[][] likeQueries() {
return new Object[][]{
{"hive_table where name like \"sa?es*\"", 3},
{"hive_db where name like \"R*\"", 1},
......@@ -542,134 +359,23 @@ public class DSLQueriesTest extends BasicTestSetup {
};
}
@Test(dataProvider = "comparisonQueriesProvider")
public void testLikeQueries(String query, int expected) throws AtlasBaseException {
@Test(dataProvider = "likeQueriesProvider")
public void likeQueries(String query, int expected) throws AtlasBaseException {
AtlasSearchResult searchResult = discoveryService.searchUsingDslQuery(query, 25, 0);
assertNotNull(searchResult.getEntities());
assertEquals(searchResult.getEntities().size(), expected);
assertSearchResult(searchResult, expected);
}
// TODO: Implement FieldValidator with new Data types
// @DataProvider(name = "dslGroupByQueriesProvider")
// private Object[][] createDSLGroupByQueries() {
// return new Object[][]{
// { "from Person as p, mentor as m groupby(m.name) select m.name, count()",
// new FieldValueValidator().withFieldNames("m.name", "count()").withExpectedValues("Max", 1)
// .withExpectedValues("Julius", 1) },
//
// // This variant of this query is currently failing. See OMS-335 for details.
// { "from Person as p, mentor groupby(mentor.name) select mentor.name, count()",
// new FieldValueValidator().withFieldNames("mentor.name", "count()").withExpectedValues("Max", 1)
// .withExpectedValues("Julius", 1) },
//
// { "from Person, mentor groupby(mentor.name) select mentor.name, count()",
// new FieldValueValidator().withFieldNames("mentor.name", "count()").withExpectedValues("Max", 1)
// .withExpectedValues("Julius", 1) },
//
// { "from Person, mentor as m groupby(m.name) select m.name, count()",
// new FieldValueValidator().withFieldNames("m.name", "count()").withExpectedValues("Max", 1)
// .withExpectedValues("Julius", 1) },
//
// { "from Person groupby (isOrganDonor) select count()",
// new FieldValueValidator().withFieldNames("count()").withExpectedValues(2)
// .withExpectedValues(2) },
// { "from Person groupby (isOrganDonor) select Person.isOrganDonor, count()",
// new FieldValueValidator().withFieldNames("Person.isOrganDonor", "count()")
// .withExpectedValues(true, 2).withExpectedValues(false, 2) },
//
// { "from Person groupby (isOrganDonor) select Person.isOrganDonor as 'organDonor', count() as 'count', max(Person.age) as 'max', min(Person.age) as 'min'",
// new FieldValueValidator().withFieldNames("organDonor", "max", "min", "count")
// .withExpectedValues(true, 50, 36, 2).withExpectedValues(false, 0, 0, 2) },
//
// { "from hive_db groupby (owner, name) select count() ", new FieldValueValidator()
// .withFieldNames("count()").withExpectedValues(1).withExpectedValues(1).withExpectedValues(1) },
//
// { "from hive_db groupby (owner, name) select hive_db.owner, hive_db.name, count() ",
// new FieldValueValidator().withFieldNames("hive_db.owner", "hive_db.name", "count()")
// .withExpectedValues("Jane BI", "Reporting", 1)
// .withExpectedValues("Tim ETL", "Logging", 1)
// .withExpectedValues("John ETL", "Sales", 1) },
//
// { "from hive_db groupby (owner) select count() ",
// new FieldValueValidator().withFieldNames("count()").withExpectedValues(1).withExpectedValues(1)
// .withExpectedValues(1) },
//
// { "from hive_db groupby (owner) select hive_db.owner, count() ",
// new FieldValueValidator().withFieldNames("hive_db.owner", "count()")
// .withExpectedValues("Jane BI", 1).withExpectedValues("Tim ETL", 1)
// .withExpectedValues("John ETL", 1) },
//
// { "from hive_db groupby (owner) select hive_db.owner, max(hive_db.name) ",
// new FieldValueValidator().withFieldNames("hive_db.owner", "max(hive_db.name)")
// .withExpectedValues("Tim ETL", "Logging").withExpectedValues("Jane BI", "Reporting")
// .withExpectedValues("John ETL", "Sales") },
//
// { "from hive_db groupby (owner) select max(hive_db.name) ",
// new FieldValueValidator().withFieldNames("max(hive_db.name)").withExpectedValues("Logging")
// .withExpectedValues("Reporting").withExpectedValues("Sales") },
//
// { "from hive_db groupby (owner) select owner, hive_db.name, min(hive_db.name) ",
// new FieldValueValidator().withFieldNames("owner", "hive_db.name", "min(hive_db.name)")
// .withExpectedValues("Tim ETL", "Logging", "Logging")
// .withExpectedValues("Jane BI", "Reporting", "Reporting")
// .withExpectedValues("John ETL", "Sales", "Sales") },
//
// { "from hive_db groupby (owner) select owner, min(hive_db.name) ",
// new FieldValueValidator().withFieldNames("owner", "min(hive_db.name)")
// .withExpectedValues("Tim ETL", "Logging").withExpectedValues("Jane BI", "Reporting")
// .withExpectedValues("John ETL", "Sales") },
//
// { "from hive_db groupby (owner) select min(name) ",
// new FieldValueValidator().withFieldNames("min(name)")
// .withExpectedValues("Reporting").withExpectedValues("Logging")
// .withExpectedValues("Sales") },
//
// { "from hive_db groupby (owner) select min('name') ",
// new FieldValueValidator().withFieldNames("min(\"name\")").withExpectedValues("name")
// .withExpectedValues("name").withExpectedValues("name") }, //finding the minimum of a constant literal expression...
//
// { "from hive_db groupby (owner) select name ",
// new FieldValueValidator().withFieldNames("name").withExpectedValues("Reporting")
// .withExpectedValues("Sales").withExpectedValues("Logging") },
//
// //implied group by
// { "from hive_db select count() ",
// new FieldValueValidator().withFieldNames("count()").withExpectedValues(3) },
// //implied group by
// { "from Person select count() as 'count', max(Person.age) as 'max', min(Person.age) as 'min'",
// new FieldValueValidator().withFieldNames("max", "min", "count").withExpectedValues(50, 0, 4) },
// //Sum
// { "from Person groupby (isOrganDonor) select count() as 'count', sum(Person.age) as 'sum'",
// new FieldValueValidator().withFieldNames("count", "sum").withExpectedValues(2, 0)
// .withExpectedValues(2, 86) },
// { "from Person groupby (isOrganDonor) select Person.isOrganDonor as 'organDonor', count() as 'count', sum(Person.age) as 'sum'",
// new FieldValueValidator().withFieldNames("organDonor", "count", "sum").withExpectedValues(false, 2, 0)
// .withExpectedValues(true, 2, 86) },
// { "from Person select count() as 'count', sum(Person.age) as 'sum'",
// new FieldValueValidator().withFieldNames("count", "sum").withExpectedValues(4, 86) },
// // tests to ensure that group by works with order by and limit
// { "from hive_db groupby (owner) select min(name) orderby name limit 2 ",
// new FieldValueValidator().withFieldNames("min(name)")
// .withExpectedValues("Logging").withExpectedValues("Reporting")
// },
//
// { "from hive_db groupby (owner) select min(name) orderby name desc limit 2 ",
// new FieldValueValidator().withFieldNames("min(name)")
// .withExpectedValues("Reporting").withExpectedValues("Sales")
// },
// };
// }
//
// @DataProvider(name = "dslObjectQueriesReturnIdProvider")
// private Object[][] createDSLObjectIdQueries() {
// return new Object[][] { {
// "from hive_db as h select h as id",
// new FieldValueValidator().withFieldNames("id")
// .withExpectedValues(idType).withExpectedValues(idType)
// .withExpectedValues(idType) }
// };
// }
private void assertSearchResult(AtlasSearchResult searchResult, int expected) {
assertNotNull(searchResult);
if(expected == 0) {
assertNull(searchResult.getAttributes());
assertNull(searchResult.getEntities());
} else if(searchResult.getEntities() != null) {
assertEquals(searchResult.getEntities().size(), expected);
} else {
assertNotNull(searchResult.getAttributes());
assertNotNull(searchResult.getAttributes().getValues());
assertEquals(searchResult.getAttributes().getValues().size(), expected);
}
}
}
......@@ -22,6 +22,8 @@ import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.TokenStream;
import org.apache.atlas.query.antlr4.AtlasDSLLexer;
import org.apache.atlas.query.antlr4.AtlasDSLParser;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.commons.lang.StringUtils;
import org.testng.annotations.Test;
......@@ -32,8 +34,10 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
......@@ -43,7 +47,7 @@ public class QueryProcessorTest {
private List<String> errorList = new ArrayList<>();
@Test
public void trait() {
public void classification() {
String expected = "g.V().has('__traitNames', within('PII')).limit(25).toList()";
verify("PII", expected);
}
......@@ -54,19 +58,21 @@ public class QueryProcessorTest {
verify("Table isa Dimension", expected);
verify("Table is Dimension", expected);
verify("Table where Table is Dimension", expected);
verify("Table isa Dimension where name = 'sales'",
"g.V().has('__typeName', 'Table').has('__traitNames', within('Dimension')).has('Table.name', eq('sales')).limit(25).toList()");
}
@Test
public void fromDB() {
verify("from DB", "g.V().has('__typeName', 'DB').limit(25).toList()");
verify("from DB limit 10", "g.V().has('__typeName', 'DB').order().limit(10).toList()");
verify("from DB limit 10", "g.V().has('__typeName', 'DB').limit(10).toList()");
verify("DB limit 10", "g.V().has('__typeName', 'DB').limit(10).toList()");
}
@Test
public void DBHasName() {
String expected = "g.V().has('__typeName', 'DB').has('DB.name').limit(25).toList()";
verify("DB has name", expected);
// verify("DB has name", expected);
verify("DB where DB has name", expected);
}
......@@ -76,33 +82,39 @@ public class QueryProcessorTest {
}
@Test
public void tableSelectColumns() {
verify("Table select Columns limit 10", "g.V().has('__typeName', 'Table').out('__Table.columns').as('s0').select('s0').order().limit(10).toList()");
}
@Test
public void DBasDSelect() {
String expected = "g.V().has('__typeName', 'DB').as('d').valueMap('DB.name', 'DB.owner')";
String expected = "g.V().has('__typeName', 'DB').as('d').valueMap('DB.name','DB.owner')";
verify("DB as d select d.name, d.owner", expected + ".limit(25).toList()");
verify("DB as d select d.name, d.owner limit 10", expected + ".order().limit(10).toList()");
verify("DB as d select d.name, d.owner limit 10", expected + ".limit(10).toList()");
}
@Test
public void tableSelectColumns() {
verify("Table select columns limit 10", "g.V().has('__typeName', 'Table').out('__Table.columns').as('s0').select('s0').limit(10).toList()");
verify("Table select db.name", "g.V().has('__typeName', 'Table').out('__DB.Table').as('s0').select('s0').limit(25).toList()");
}
@Test(enabled = false)
public void DBTableFrom() {
verify("DB, Table", "g.V().has('__typeName', 'DB').out('__DB.Table').limit(25).toList()");
verify("Table, db", "g.V().has('__typeName', 'Table').out('__DB.Table').limit(25).toList()");
}
@Test
public void DBAsDSelectLimit() {
verify("from DB limit 5", "g.V().has('__typeName', 'DB').order().limit(5).toList()");
verify("from DB limit 5 offset 2", "g.V().has('__typeName', 'DB').order().range(2, 2 + 5).limit(25).toList()");
verify("from DB limit 5", "g.V().has('__typeName', 'DB').limit(5).toList()");
verify("from DB limit 5 offset 2", "g.V().has('__typeName', 'DB').range(2, 2 + 5).limit(25).toList()");
}
@Test
public void DBOrderBy() {
String expected = "g.V().has('__typeName', 'DB').order().by('DB.name').limit(25).toList()";
// verify("DB orderby name", expected);
verify("DB orderby name", expected);
verify("from DB orderby name", expected);
verify("from DB as d orderby d.owner limit 3", "g.V().has('__typeName', 'DB').as('d').order().by('DB.owner').limit(3).toList()");
verify("DB as d orderby d.owner limit 3", "g.V().has('__typeName', 'DB').as('d').order().by('DB.owner').limit(3).toList()");
verify("DB as d select name, owner orderby d.owner limit 3", "g.V().has('__typeName', 'DB').as('d').order().by('DB.owner').valueMap('DB.name','DB.owner').limit(3).toList()");
verify("Table where (name = \"sales_fact\" and createTime > \"2014-01-01\" ) select name as _col_0, createTime as _col_1 orderby _col_1",
"g.V().has('__typeName', 'Table').and(__.has('Table.name', eq(\"sales_fact\")),__.has('Table.createTime', gt('1388563200000'))).order().by('Table.createTime').valueMap('Table.name','Table.createTime').limit(25).toList()");
}
@Test
......@@ -112,7 +124,7 @@ public class QueryProcessorTest {
@Test
public void fromDBSelect() {
verify("from DB select DB.name, DB.owner", "g.V().has('__typeName', 'DB').valueMap('DB.name', 'DB.owner').limit(25).toList()");
verify("from DB select DB.name, DB.owner", "g.V().has('__typeName', 'DB').valueMap('DB.name','DB.owner').limit(25).toList()");
}
@Test
......@@ -122,31 +134,37 @@ public class QueryProcessorTest {
@Test
public void whereClauseTextContains() {
String expected = "g.V().has('__typeName', 'DB').has('DB.name', eq(\"Reporting\")).valueMap('DB.name', 'DB.owner').limit(25).toList()";
verify("from DB where name = \"Reporting\" select name, owner)", expected);
String expected = "g.V().has('__typeName', 'DB').has('DB.name', eq(\"Reporting\")).valueMap('DB.name','DB.owner').limit(25).toList()";
verify("from DB where name = \"Reporting\" select name, owner", expected);
verify("Table where Asset.name like \"Tab*\"",
"g.V().has('__typeName', 'Table').has('Asset.name', org.janusgraph.core.attribute.Text.textContainsRegex(\"Tab.*\")).limit(25).toList()");
"g.V().has('__typeName', 'Table').has('Table.name', org.janusgraph.core.attribute.Text.textRegex(\"Tab.*\")).limit(25).toList()");
verify("from DB where (name = \"Reporting\") select name, owner", expected);
verify("from DB as db1 Table where (db1.name = \"Reporting\") select name, owner",
"g.V().has('__typeName', 'DB').as('db1').out('__DB.Table').has('DB.name', eq(\"Reporting\")).valueMap('Column.name', 'Column.owner').limit(25).toList()");
verify("from Table where (db.name = \"Reporting\")",
"g.V().has('__typeName', 'Table').out('__DB.Table').has('DB.name', eq(\"Reporting\")).in('__DB.Table').limit(25).toList()");
}
@Test
public void whereClauseWithAsTextContains() {
verify("Table as t where t.name = \"testtable_1\" select t.name, t.owner)",
"g.V().has('__typeName', 'Table').as('t').has('Table.name', eq(\"testtable_1\")).valueMap('Table.name', 'Table.owner').limit(25).toList()");
"g.V().has('__typeName', 'Table').as('t').has('Table.name', eq(\"testtable_1\")).valueMap('Table.name','Table.owner').limit(25).toList()");
}
@Test
public void whereClauseWithDateCompare() {
verify("Table as t where t.createdTime = \"2017-12-12T02:35:58.440Z\" select t.name, t.owner)",
"g.V().has('__typeName', 'Table').as('t').has('Table.createdTime', eq('1513046158440')).valueMap('Table.name','Table.owner').limit(25).toList()");
}
@Test
public void multipleWhereClauses() {
verify("Table where name=\"sales_fact\", columns as c select c.owner, c.name, c.dataType",
"g.V().has('__typeName', 'Table').has('Table.name', eq(\"sales_fact\")).out('__Table.columns').as('c').valueMap('Column.owner', 'Column.name', 'Column.dataType').limit(25).toList()");
"g.V().has('__typeName', 'Table').has('Table.name', eq(\"sales_fact\")).out('__Table.columns').as('c').valueMap('Column.owner','Column.name','Column.dataType').limit(25).toList()");
}
@Test
public void subType() {
verify("Asset select name, owner",
"g.V().has('__typeName', within('Asset','Table')).valueMap('Asset.name', 'Asset.owner').limit(25).toList()");
"g.V().has('__typeName', within('Asset','Table')).valueMap('Asset.name','Asset.owner').limit(25).toList()");
}
@Test
......@@ -154,6 +172,73 @@ public class QueryProcessorTest {
verify("`Log Data`", "g.V().has('__typeName', 'Log Data').limit(25).toList()");
}
@Test
public void nestedQueries() {
verify("Table where name=\"sales_fact\" or name=\"testtable_1\"",
"g.V().has('__typeName', 'Table').or(__.has('Table.name', eq(\"sales_fact\")),__.has('Table.name', eq(\"testtable_1\"))).limit(25).toList()");
verify("Table where name=\"sales_fact\" and name=\"testtable_1\"",
"g.V().has('__typeName', 'Table').and(__.has('Table.name', eq(\"sales_fact\")),__.has('Table.name', eq(\"testtable_1\"))).limit(25).toList()");
verify("Table where name=\"sales_fact\" or name=\"testtable_1\" or name=\"testtable_2\"",
"g.V().has('__typeName', 'Table')" +
".or(" +
"__.has('Table.name', eq(\"sales_fact\"))," +
"__.has('Table.name', eq(\"testtable_1\"))," +
"__.has('Table.name', eq(\"testtable_2\"))" +
").limit(25).toList()");
verify("Table where name=\"sales_fact\" and name=\"testtable_1\" and name=\"testtable_2\"",
"g.V().has('__typeName', 'Table')" +
".and(" +
"__.has('Table.name', eq(\"sales_fact\"))," +
"__.has('Table.name', eq(\"testtable_1\"))," +
"__.has('Table.name', eq(\"testtable_2\"))" +
").limit(25).toList()");
verify("Table where (name=\"sales_fact\" or name=\"testtable_1\") and name=\"testtable_2\"",
"g.V().has('__typeName', 'Table')" +
".and(" +
"__.or(" +
"__.has('Table.name', eq(\"sales_fact\"))," +
"__.has('Table.name', eq(\"testtable_1\"))" +
")," +
"__.has('Table.name', eq(\"testtable_2\")))" +
".limit(25).toList()");
verify("Table where name=\"sales_fact\" or (name=\"testtable_1\" and name=\"testtable_2\")",
"g.V().has('__typeName', 'Table')" +
".or(" +
"__.has('Table.name', eq(\"sales_fact\"))," +
"__.and(" +
"__.has('Table.name', eq(\"testtable_1\"))," +
"__.has('Table.name', eq(\"testtable_2\")))" +
")" +
".limit(25).toList()");
verify("Table where name=\"sales_fact\" or name=\"testtable_1\" and name=\"testtable_2\"",
"g.V().has('__typeName', 'Table')" +
".and(" +
"__.or(" +
"__.has('Table.name', eq(\"sales_fact\"))," +
"__.has('Table.name', eq(\"testtable_1\"))" +
")," +
"__.has('Table.name', eq(\"testtable_2\")))" +
".limit(25).toList()");
verify("Table where (name=\"sales_fact\" and owner=\"Joe\") OR (name=\"sales_fact_daily_mv\" and owner=\"Joe BI\")",
"g.V().has('__typeName', 'Table')" +
".or(" +
"__.and(" +
"__.has('Table.name', eq(\"sales_fact\"))," +
"__.has('Table.owner', eq(\"Joe\"))" +
")," +
"__.and(" +
"__.has('Table.name', eq(\"sales_fact_daily_mv\"))," +
"__.has('Table.owner', eq(\"Joe BI\"))" +
"))" +
".limit(25).toList()");
verify("Table where owner=\"hdfs\" or ((name=\"testtable_1\" or name=\"testtable_2\") and createdTime < \"2017-12-12T02:35:58.440Z\")",
"g.V().has('__typeName', 'Table').or(__.has('Table.owner', eq(\"hdfs\")),__.and(__.or(__.has('Table.name', eq(\"testtable_1\")),__.has('Table.name', eq(\"testtable_2\"))),__.has('Table.createdTime', lt('1513046158440')))).limit(25).toList()");
verify("hive_db where hive_db.name='Reporting' and hive_db.createTime < '2017-12-12T02:35:58.440Z'",
"g.V().has('__typeName', 'hive_db').and(__.has('hive_db.name', eq('Reporting')),__.has('hive_db.createTime', lt('1513046158440'))).limit(25).toList()");
verify("Table where db.name='Sales' and db.clusterName='cl1'",
"g.V().has('__typeName', 'Table').and(__.out('__DB.Table').has('DB.name', eq('Sales')).in('__DB.Table'),__.out('__DB.Table').has('DB.clusterName', eq('cl1')).in('__DB.Table')).limit(25).toList()");
}
private void verify(String dsl, String expectedGremlin) {
AtlasDSLParser.QueryContext queryContext = getParsedQuery(dsl);
String actualGremlin = getGremlinQuery(queryContext);
......@@ -182,7 +267,11 @@ public class QueryProcessorTest {
}
private String getGremlinQuery(AtlasDSLParser.QueryContext queryContext) {
QueryProcessor queryProcessor = new QueryProcessor(new TestTypeRegistryLookup(errorList, mock(AtlasTypeRegistry.class)));
AtlasTypeRegistry registry = mock(AtlasTypeRegistry.class);
org.apache.atlas.query.Lookup lookup = new TestLookup(errorList, registry);
QueryProcessor.Context context = new QueryProcessor.Context(errorList, lookup);
QueryProcessor queryProcessor = new QueryProcessor(lookup, context);
DSLVisitor qv = new DSLVisitor(queryProcessor);
qv.visit(queryContext);
queryProcessor.close();
......@@ -191,84 +280,94 @@ public class QueryProcessorTest {
return queryProcessor.getText();
}
private static class TestTypeRegistryLookup extends QueryProcessor.TypeRegistryLookup {
private String activeType;
private HashMap<String, String> asContext = new HashMap<>();
public TestTypeRegistryLookup(List<String> errorList, AtlasTypeRegistry typeRegistry) {
super(errorList, typeRegistry);
}
private static class TestLookup implements org.apache.atlas.query.Lookup {
public void registerActive(String typeName) {
activeType = typeName;
}
List<String> errorList;
AtlasTypeRegistry registry;
public boolean hasActiveType() {
return !StringUtils.isEmpty(activeType);
public TestLookup(List<String> errorList, AtlasTypeRegistry typeRegistry) {
this.errorList = errorList;
this.registry = typeRegistry;
}
public void registerStepType(String stepName) {
if (!asContext.containsKey(stepName)) {
asContext.put(stepName, activeType);
@Override
public AtlasType getType(String typeName) {
AtlasType type = null;
if(typeName.equals("PII") || typeName.equals("Dimension")) {
type = mock(AtlasType.class);
} else {
addError(String.format("Multiple steps with same name detected: %s", stepName));
}
type = mock(AtlasEntityType.class);
}
public String getRelationshipEdgeLabelForActiveType(String item) {
if(item.equalsIgnoreCase("columns"))
return "__Table.columns";
else
return "__DB.Table";
when(type.getTypeName()).thenReturn(typeName);
return type;
}
public String getQualifiedAttributeName(String item) {
if (item.contains(".")) {
String[] keyValue = StringUtils.split(item, ".");
@Override
public String getQualifiedName(QueryProcessor.Context context, String name) {
if(name.contains("."))
return name;
if (!asContext.containsKey(keyValue[0])) {
return item;
} else {
String s = getStitchedString(keyValue, 1, keyValue.length - 1);
return getDefaultQualifiedAttributeNameFromType(asContext.get(keyValue[0]), s);
}
return String.format("%s.%s", context.getActiveTypeName(), name);
}
return getDefaultQualifiedAttributeNameFromType(activeType, item);
@Override
public boolean isPrimitive(QueryProcessor.Context context, String attributeName) {
return attributeName.equals("name") ||
attributeName.equals("owner") ||
attributeName.equals("createdTime") ||
attributeName.equals("createTime") ||
attributeName.equals("clusterName");
}
public String getDefaultQualifiedAttributeNameFromType(String s, String item) {
return StringUtils.isEmpty(s) ? item : String.format("%s.%s", s, item);
@Override
public String getRelationshipEdgeLabel(QueryProcessor.Context context, String attributeName) {
if (attributeName.equalsIgnoreCase("columns"))
return "__Table.columns";
else
return "__DB.Table";
}
@Override
public String getTypeFromEdge(String item) {
return "Column";
public boolean hasAttribute(QueryProcessor.Context context, String typeName) {
return (context.getActiveTypeName().equals("Table") && typeName.equals("db")) ||
(context.getActiveTypeName().equals("Table") && typeName.equals("columns"));
}
@Override
public boolean isAttributePrimitiveTypeForActiveType(String s) {
return s.equalsIgnoreCase("name") || s.equalsIgnoreCase("owner");
public boolean doesTypeHaveSubTypes(QueryProcessor.Context context) {
return context.getActiveTypeName().equalsIgnoreCase("Asset");
}
@Override
public boolean isTypeTrait(String name) {
return name.equalsIgnoreCase("PII");
public String getTypeAndSubTypes(QueryProcessor.Context context) {
String[] str = new String[]{"'Asset'", "'Table'"};
return StringUtils.join(str, ",");
}
public boolean doesActiveTypeHaveSubTypes() {
return activeType.equalsIgnoreCase("Asset");
@Override
public boolean isTraitType(QueryProcessor.Context context) {
return context.getActiveTypeName().equals("PII") || context.getActiveTypeName().equals("Dimension");
}
public String getActiveTypeAndSubTypes() {
String[] str = new String[]{"'Asset'", "'Table'"};
return StringUtils.join(str, ",");
@Override
public String getTypeFromEdge(QueryProcessor.Context context, String item) {
if(context.getActiveTypeName().equals("DB") && item.equals("Table")) {
return "Table";
} else if(context.getActiveTypeName().equals("Table") && item.equals("Column")) {
return "Column";
} else if(context.getActiveTypeName().equals("Table") && item.equals("db")) {
return "DB";
} else if(context.getActiveTypeName().equals("Table") && item.equals("columns")) {
return "Column";
}
return context.getActiveTypeName();
}
@Override
public boolean isSameAsActive(String typeName) {
return (activeType != null) && activeType.equalsIgnoreCase(typeName);
public boolean isDate(QueryProcessor.Context context, String attributeName) {
return attributeName.equals("createdTime") ||
attributeName.equals("createTime");
}
}
}
......@@ -24,7 +24,10 @@ import com.google.common.base.Preconditions;
import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasConfiguration;
import org.apache.atlas.classification.InterfaceAudience;
import org.apache.atlas.discovery.AtlasDiscoveryService;
import org.apache.atlas.model.discovery.AtlasSearchResult;
import org.apache.atlas.query.QueryParams;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.utils.AtlasJson;
import org.apache.atlas.utils.AtlasPerfTracer;
import org.apache.atlas.utils.ParamChecker;
......@@ -68,6 +71,7 @@ public class MetadataDiscoveryResource {
private final boolean gremlinSearchEnabled;
private static Configuration applicationProperties = null;
private static final String ENABLE_GREMLIN_SEARCH_PROPERTY = "atlas.search.gremlin.enable";
private final AtlasDiscoveryService atlasDiscoveryService;
/**
* Created by the Guice ServletModule and injected with the
......@@ -76,7 +80,8 @@ public class MetadataDiscoveryResource {
* @param configuration configuration
*/
@Inject
public MetadataDiscoveryResource(Configuration configuration) {
public MetadataDiscoveryResource(AtlasDiscoveryService atlasDiscoveryService, Configuration configuration) {
this.atlasDiscoveryService = atlasDiscoveryService;
applicationProperties = configuration;
gremlinSearchEnabled = applicationProperties != null && applicationProperties.getBoolean(ENABLE_GREMLIN_SEARCH_PROPERTY, false);
}
......@@ -149,7 +154,8 @@ public class MetadataDiscoveryResource {
dslQuery = ParamChecker.notEmpty(dslQuery, "dslQuery cannot be null");
QueryParams queryParams = validateQueryParams(limit, offset);
final String jsonResultStr = ""; // TODO-typeSystem-removal: discoveryService.searchByDSL(dslQuery, queryParams);
AtlasSearchResult result = atlasDiscoveryService.searchUsingDslQuery(dslQuery, queryParams.limit(), queryParams.offset());
final String jsonResultStr = AtlasType.toJson(result.getEntities());
ObjectNode response = new DSLJSONResponseBuilder().results(jsonResultStr).query(dslQuery).build();
......@@ -195,62 +201,6 @@ public class MetadataDiscoveryResource {
}
/**
* Search using raw gremlin query format.
*
* @param gremlinQuery search query in raw gremlin format.
* @return JSON representing the type and results.
*/
@GET
@Path("search/gremlin")
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
@InterfaceAudience.Private
public Response searchUsingGremlinQuery(@QueryParam("query") String gremlinQuery) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> MetadataDiscoveryResource.searchUsingGremlinQuery({})", gremlinQuery);
}
AtlasPerfTracer perf = null;
try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "MetadataDiscoveryResource.searchUsingGremlinQuery(" + gremlinQuery + ")");
}
if (!gremlinSearchEnabled) {
throw new Exception("Gremlin search is not enabled.");
}
gremlinQuery = ParamChecker.notEmpty(gremlinQuery, "gremlinQuery cannot be null or empty");
final List<Map<String, String>> results = new ArrayList<>(); // TODO-typeSystem-removal: discoveryService.searchByGremlin(gremlinQuery);
ObjectNode response = AtlasJson.createV1ObjectNode();
response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId());
response.put(AtlasClient.QUERY, gremlinQuery);
response.put(AtlasClient.QUERY_TYPE, QUERY_TYPE_GREMLIN);
response.putPOJO(AtlasClient.RESULTS, results);
response.put(AtlasClient.COUNT, results.size());
return Response.ok(response).build();
} catch (IllegalArgumentException e) {
LOG.error("Unable to get entity list for gremlinQuery {}", gremlinQuery, e);
throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
} catch (WebApplicationException e) {
LOG.error("Unable to get entity list for gremlinQuery {}", gremlinQuery, e);
throw e;
} catch (Throwable e) {
LOG.error("Unable to get entity list for gremlinQuery {}", gremlinQuery, e);
throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
} finally {
AtlasPerfTracer.log(perf);
if (LOG.isDebugEnabled()) {
LOG.debug("<== MetadataDiscoveryResource.searchUsingGremlinQuery({})", gremlinQuery);
}
}
}
/**
* Search using full text search.
*
* @param query search query.
......@@ -277,7 +227,8 @@ public class MetadataDiscoveryResource {
query = ParamChecker.notEmpty(query, "query cannot be null or empty");
QueryParams queryParams = validateQueryParams(limit, offset);
final String jsonResultStr = ""; // TODO-typeSystem-removal: discoveryService.searchByFullText(query, queryParams);
AtlasSearchResult result = atlasDiscoveryService.searchUsingFullTextQuery(query, false, queryParams.limit(), queryParams.offset());
final String jsonResultStr = AtlasType.toJson(result.getEntities());
ArrayNode rowsJsonArr = AtlasJson.parseToV1ArrayNode(jsonResultStr);
ObjectNode response = new FullTextJSonResponseBuilder().results(rowsJsonArr).query(query).build();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment