Commit 8bb3e853 by Madhan Neethiraj

ATLAS-3983: solr index query escape character handling

parent 4f95ee8c
......@@ -65,7 +65,7 @@ public class AtlasClassificationType extends AtlasStructType {
super(classificationDef);
this.classificationDef = classificationDef;
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()), true);
}
/**
......@@ -81,7 +81,7 @@ public class AtlasClassificationType extends AtlasStructType {
super(classificationDef);
this.classificationDef = classificationDef;
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()), true);
resolveReferences(typeRegistry);
}
......@@ -264,7 +264,7 @@ public class AtlasClassificationType extends AtlasStructType {
public String getTypeAndAllSubTypesQryStr() {
if (StringUtils.isEmpty(typeAndAllSubTypesQryStr)) {
typeAndAllSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(typeAndAllSubTypes);
typeAndAllSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(typeAndAllSubTypes, true);
}
return typeAndAllSubTypesQryStr;
......
......@@ -100,7 +100,7 @@ public class AtlasEntityType extends AtlasStructType {
super(entityDef);
this.entityDef = entityDef;
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()), true);
this.displayTextAttribute = entityDef.getOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE);
}
......@@ -108,7 +108,7 @@ public class AtlasEntityType extends AtlasStructType {
super(entityDef);
this.entityDef = entityDef;
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()));
this.typeQryStr = AtlasAttribute.escapeIndexQueryValue(Collections.singleton(getTypeName()), true);
this.displayTextAttribute = entityDef.getOption(AtlasEntityDef.OPTION_DISPLAY_TEXT_ATTRIBUTE);
resolveReferences(typeRegistry);
......@@ -573,7 +573,7 @@ public class AtlasEntityType extends AtlasStructType {
public String getTypeAndAllSubTypesQryStr() {
if (StringUtils.isEmpty(typeAndAllSubTypesQryStr)) {
typeAndAllSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(typeAndAllSubTypes);
typeAndAllSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(typeAndAllSubTypes, true);
}
return typeAndAllSubTypesQryStr;
......
......@@ -936,6 +936,10 @@ public class AtlasStructType extends AtlasType {
}
public static String escapeIndexQueryValue(Collection<String> values) {
return escapeIndexQueryValue(values, false);
}
public static String escapeIndexQueryValue(Collection<String> values, boolean allowWildcard) {
StringBuilder sb = new StringBuilder();
sb.append(BRACE_OPEN_CHAR);
......@@ -943,10 +947,10 @@ public class AtlasStructType extends AtlasType {
if (CollectionUtils.isNotEmpty(values)) {
Iterator<String> iter = values.iterator();
sb.append(escapeIndexQueryValue(iter.next()));
sb.append(escapeIndexQueryValue(iter.next(), allowWildcard));
while (iter.hasNext()) {
sb.append(SPACE_CHAR).append(escapeIndexQueryValue(iter.next()));
sb.append(SPACE_CHAR).append(escapeIndexQueryValue(iter.next(), allowWildcard));
}
}
......@@ -956,26 +960,109 @@ public class AtlasStructType extends AtlasType {
}
public static String escapeIndexQueryValue(String value) {
String ret = value;
return escapeIndexQueryValue(value, false);
}
public static String escapeIndexQueryValue(String value, boolean allowWildcard) {
String ret = value;
boolean quoteValue = false;
if (hasIndexQueryEscapeChar(value)) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (!(allowWildcard && c == '*') && isIndexQueryEscapeChar(c)) {
sb.append('\\');
}
if (!quoteValue) {
quoteValue = shouldQuoteIndexQueryForChar(c);
}
sb.append(c);
}
ret = sb.toString();
} else if (value != null) {
for (int i = 0; i < value.length(); i++) {
if (shouldQuoteIndexQueryForChar(value.charAt(i))) {
quoteValue = true;
break;
}
}
}
if (StringUtils.containsAny(value, IDX_QRY_OFFENDING_CHARS)) {
boolean isQuoteAtStart = value.charAt(0) == DOUBLE_QUOTE_CHAR;
boolean isQuoteAtEnd = value.charAt(value.length() - 1) == DOUBLE_QUOTE_CHAR;
if (quoteValue) {
boolean isQuoteAtStart = ret.charAt(0) == DOUBLE_QUOTE_CHAR;
boolean isQuoteAtEnd = ret.charAt(ret.length() - 1) == DOUBLE_QUOTE_CHAR;
if (!isQuoteAtStart) {
if (!isQuoteAtEnd) {
ret = DOUBLE_QUOTE_CHAR + value + DOUBLE_QUOTE_CHAR;
ret = DOUBLE_QUOTE_CHAR + ret + DOUBLE_QUOTE_CHAR;
} else {
ret = DOUBLE_QUOTE_CHAR + value;
ret = DOUBLE_QUOTE_CHAR + ret;
}
} else if (!isQuoteAtEnd) {
ret = value + DOUBLE_QUOTE_CHAR;
ret = ret + DOUBLE_QUOTE_CHAR;
}
}
return ret;
}
private static boolean hasIndexQueryEscapeChar(String value) {
if (value != null) {
for (int i = 0; i < value.length(); i++) {
if (isIndexQueryEscapeChar(value.charAt(i))) {
return true;
}
}
}
return false;
}
private static boolean isIndexQueryEscapeChar(char c) {
switch (c) {
case '+':
case '-':
case '&':
case '|':
case '!':
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
case '^':
case '"':
case '~':
case '*':
case '?':
case ':':
case '\\':
case '/':
return true;
}
return false;
}
private static boolean shouldQuoteIndexQueryForChar(char c) {
switch (c) {
case '@':
case ' ':
return true;
}
return false;
}
private String getRelationshipEdgeLabel(String relationshipLabel) {
return (relationshipLabel == null) ? getEdgeLabel(qualifiedName) : relationshipLabel;
}
......@@ -1024,7 +1111,6 @@ public class AtlasStructType extends AtlasType {
new String[] {"%", "_p"}, //titan reserved characters
};
private static final char[] IDX_QRY_OFFENDING_CHARS = { '@', '/', ' ', '-' };
private static final char BRACE_OPEN_CHAR = '(';
private static final char BRACE_CLOSE_CHAR = ')';
private static final char DOUBLE_QUOTE_CHAR = '"';
......
......@@ -17,9 +17,7 @@
*/
package org.apache.atlas.discovery;
import static org.apache.atlas.discovery.SearchContext.MATCH_ALL_CLASSIFIED;
import static org.apache.atlas.discovery.SearchContext.MATCH_ALL_NOT_CLASSIFIED;
import static org.apache.atlas.discovery.SearchContext.MATCH_ALL_WILDCARD_CLASSIFICATION;
import static org.apache.atlas.discovery.SearchProcessor.INDEX_SEARCH_PREFIX;
import static org.apache.atlas.repository.Constants.CLASSIFICATION_NAMES_KEY;
import static org.apache.atlas.repository.Constants.PROPAGATED_CLASSIFICATION_NAMES_KEY;
......@@ -39,7 +37,7 @@ public class GraphIndexQueryBuilder {
void addClassificationTypeFilter(StringBuilder indexQuery) {
if (indexQuery != null && CollectionUtils.isNotEmpty(context.getClassificationNames())) {
String classificationNames = AtlasStructType.AtlasAttribute.escapeIndexQueryValue(context.getClassificationNames());
String classificationNames = AtlasStructType.AtlasAttribute.escapeIndexQueryValue(context.getClassificationNames(), true);
if (indexQuery.length() != 0) {
indexQuery.append(" AND ");
}
......
......@@ -144,7 +144,7 @@ public class SearchContext {
}
if (CollectionUtils.isNotEmpty(classificationTypeAndSubTypes)) {
classificationTypeAndSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(classificationTypeAndSubTypes);
classificationTypeAndSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(classificationTypeAndSubTypes, true);
}
} else {
classificationTypeAndSubTypes = Collections.emptySet();
......@@ -171,7 +171,7 @@ public class SearchContext {
}
if (CollectionUtils.isNotEmpty(typeAndSubTypes)) {
typeAndSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(typeAndSubTypes);
typeAndSubTypesQryStr = AtlasAttribute.escapeIndexQueryValue(typeAndSubTypes, true);
}
} else {
typeAndSubTypes = Collections.emptySet();
......
......@@ -1150,24 +1150,6 @@ public abstract class SearchProcessor {
private static boolean isIndexQuerySpecialChar(char c) {
switch (c) {
case '+':
case '-':
case '&':
case '|':
case '!':
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
case '^':
case '"':
case '~':
case '*':
case '?':
case ':':
case '/':
case '#':
case '$':
case '%':
......
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