PL-5590 AST-based QueryTransformer

implement necessary methods in QueryTransformerAstBased
#PL-5590
This commit is contained in:
Eugeny Degtyarjov 2015-08-03 09:13:41 +00:00
parent d4ca43fd93
commit 4c76008fd8
3 changed files with 120 additions and 24 deletions

View File

@ -26,9 +26,10 @@ public class QueryTransformerAstBased implements QueryTransformer {
private DomainModel model;
private String query;
private String entityName;
private QueryTreeTransformer queryAnalyzer;
private QueryTreeTransformer queryTreeTransformer;
private Set<String> addedParams = new HashSet<String>();
//todo eude - resolve entity name automatically
public QueryTransformerAstBased(DomainModel model, String query, String entityName) throws RecognitionException {
this.model = model;
this.query = query;
@ -36,19 +37,20 @@ public class QueryTransformerAstBased implements QueryTransformer {
initQueryAnalyzer(model, query);
}
private void initQueryAnalyzer(DomainModel model, String query) throws RecognitionException {
queryAnalyzer = new QueryTreeTransformer();
queryAnalyzer.prepare(model, query);
List<CommonErrorNode> errorNodes = new ArrayList<CommonErrorNode>(queryAnalyzer.getErrorNodes());
List<ErrorRec> invalidIdVarNodes = queryAnalyzer.getInvalidIdVarNodes();
private void initQueryAnalyzer(DomainModel model, String query) throws RecognitionException {
queryTreeTransformer = new QueryTreeTransformer();
queryTreeTransformer.prepare(model, query);
List<CommonErrorNode> errorNodes = new ArrayList<CommonErrorNode>(queryTreeTransformer.getErrorNodes());
List<ErrorRec> invalidIdVarNodes = queryTreeTransformer.getInvalidIdVarNodes();
for (ErrorRec invalidIdVarNode : invalidIdVarNodes) {
if (errorNodes.contains(invalidIdVarNode.node)) {
errorNodes.remove(invalidIdVarNode.node);
}
}
List<ErrorRec> errors = new ArrayList<ErrorRec>(queryAnalyzer.getInvalidIdVarNodes());
List<ErrorRec> errors = new ArrayList<ErrorRec>(queryTreeTransformer.getInvalidIdVarNodes());
for (CommonErrorNode errorNode : errorNodes) {
ErrorRec rec = new ErrorRec(errorNode, "CommonErrorNode");
errors.add(rec);
@ -59,8 +61,9 @@ public class QueryTransformerAstBased implements QueryTransformer {
}
}
@Override
public String getResult() {
CommonTree tree = queryAnalyzer.getTree();
CommonTree tree = queryTreeTransformer.getTree();
TreeVisitor visitor = new TreeVisitor();
TreeToQuery treeToQuery = new TreeToQuery();
@ -82,9 +85,10 @@ public class QueryTransformerAstBased implements QueryTransformer {
* @param where - "{E}" may be used as a replaceable entity placeholder. No such value
* should be used as a string constant
*/
@Override
public void addWhere(String where) {
EntityReferenceInferer inferrer = new EntityReferenceInferer(entityName);
EntityReference ref = inferrer.infer(queryAnalyzer);
EntityReference ref = inferrer.infer(queryTreeTransformer);
boolean doReplaceVariableName = true;
if (where.contains("{E}")) {
doReplaceVariableName = false;
@ -98,6 +102,7 @@ public class QueryTransformerAstBased implements QueryTransformer {
}
}
@Override
public void addWhereAsIs(String where) {
try {
CommonTree whereTree = Parser.parseWhereClause("where " + where);
@ -112,9 +117,10 @@ public class QueryTransformerAstBased implements QueryTransformer {
*
* @param statement выражение, из которого скопировать where часть
*/
@Override
public void mergeWhere(String statement) {
EntityReferenceInferer inferer = new EntityReferenceInferer(entityName);
EntityReference ref = inferer.infer(queryAnalyzer);
EntityReference ref = inferer.infer(queryTreeTransformer);
try {
CommonTree statementTree = Parser.parse(statement);
CommonTree whereClause = (CommonTree) statementTree.getFirstChildWithType(JPA2Lexer.T_CONDITION);
@ -124,9 +130,10 @@ public class QueryTransformerAstBased implements QueryTransformer {
}
}
@Override
public void addJoinAndWhere(String join, String where) {
EntityReferenceInferer inferer = new EntityReferenceInferer(entityName);
EntityReference ref = inferer.infer(queryAnalyzer);
EntityReference ref = inferer.infer(queryTreeTransformer);
if (where.contains("{E}")) {
where = ref.replaceEntries(where, "\\{E\\}");
}
@ -137,10 +144,10 @@ public class QueryTransformerAstBased implements QueryTransformer {
join = strings[0];
try {
CommonTree joinClause = Parser.parseJoinClause(join);
queryAnalyzer.mixinJoinIntoTree(joinClause, ref, true);
queryTreeTransformer.mixinJoinIntoTree(joinClause, ref, true);
for (int i = 1; i < strings.length; i++) {
CommonTree selectionSource = Parser.parseSelectionSource(strings[i]);
queryAnalyzer.addSelectionSource(selectionSource);
queryTreeTransformer.addSelectionSource(selectionSource);
}
CommonTree whereTree = Parser.parseWhereClause("where " + where);
addWhere(whereTree, ref, false);
@ -149,25 +156,27 @@ public class QueryTransformerAstBased implements QueryTransformer {
}
}
@Override
public void addJoinAsIs(String join) {
String[] strings = join.split(",");
join = strings[0];
try {
CommonTree joinClause = Parser.parseJoinClause(join);
queryAnalyzer.mixinJoinIntoTree(joinClause, new EntityNameEntityReference(entityName), false);
queryTreeTransformer.mixinJoinIntoTree(joinClause, new EntityNameEntityReference(entityName), false);
for (int i = 1; i < strings.length; i++) {
CommonTree selectionSource = Parser.parseSelectionSource(strings[i]);
queryAnalyzer.addSelectionSource(selectionSource);
queryTreeTransformer.addSelectionSource(selectionSource);
}
} catch (RecognitionException e) {
throw new RuntimeException(e);
}
}
@Override
public void replaceWithCount() {
EntityReferenceInferer inferer = new EntityReferenceInferer(entityName);
EntityReference ref = inferer.infer(queryAnalyzer);
queryAnalyzer.replaceWithCount(ref);
EntityReference ref = inferer.infer(queryTreeTransformer);
queryTreeTransformer.replaceWithCount(ref);
}
@Override
@ -176,8 +185,7 @@ public class QueryTransformerAstBased implements QueryTransformer {
@Override
public boolean removeDistinct() {
// TODO
return false;
return queryTreeTransformer.removeDistinct();
}
@Deprecated
@ -189,20 +197,21 @@ public class QueryTransformerAstBased implements QueryTransformer {
@Override
public void replaceOrderBy(boolean desc, String... properties) {
EntityReferenceInferer inferer = new EntityReferenceInferer(entityName);
EntityReference ref = inferer.infer(queryAnalyzer);
queryAnalyzer.replaceOrderBy(ref.addFieldPath(properties[0]), desc);
EntityReference ref = inferer.infer(queryTreeTransformer);
queryTreeTransformer.replaceOrderBy(ref.addFieldPath(properties[0]), desc);
}
@Override
public void removeOrderBy() {
queryTreeTransformer.removeOrderBy();
}
@Override
public void replaceEntityName(String newName) {
// TODO
throw new UnsupportedOperationException();
queryTreeTransformer.replaceEntityName(newName);
}
@Override
public void reset() {
try {
initQueryAnalyzer(model, query);
@ -230,7 +239,7 @@ public class QueryTransformerAstBased implements QueryTransformer {
visitor.visit(whereTree, parameterCounter);
addedParams.addAll(parameterCounter.getParameterNames());
queryAnalyzer.mixinWhereConditionsIntoTree(whereTree);
queryTreeTransformer.mixinWhereConditionsIntoTree(whereTree);
}
}

View File

@ -11,6 +11,7 @@ import com.haulmont.cuba.core.sys.jpql.tree.*;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
@ -102,6 +103,46 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
tree.freshenParentAndChildIndexes();
}
public void removeOrderBy() {
Tree orderBy = tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY);
if (orderBy != null) {
tree.deleteChild(orderBy.getChildIndex());
}
tree.freshenParentAndChildIndexes();
}
public boolean removeDistinct() {
Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS);
boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText());
if (isDistinct) {
selectedItems.deleteChild(0);
} else {
return false;
}
tree.freshenParentAndChildIndexes();
return true;
}
public void replaceEntityName(String newEntityName) {
Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS);
SelectedItemNode selectedItemNode = (SelectedItemNode) selectedItems.getChild(0);
List<PathNode> pathNodes = getChildrenByClass(selectedItemNode, PathNode.class);
if (CollectionUtils.isNotEmpty(pathNodes)) {
PathNode pathNode = pathNodes.get(0);
String returnedEntityVariableName = pathNode.getEntityVariableName();
FromNode fromNode = (FromNode) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES);
SelectionSourceNode selectionSource = (SelectionSourceNode) fromNode.getFirstChildWithType(JPA2Lexer.T_SOURCE);
List<IdentificationVariableNode> identificationVariables = getChildrenByClass(selectionSource, IdentificationVariableNode.class);
for (IdentificationVariableNode identificationVariable : identificationVariables) {
if (identificationVariable.getVariableName().equalsIgnoreCase(returnedEntityVariableName)) {
identificationVariable.deleteChild(0);
identificationVariable.addChild(new CommonTree(new CommonToken(50, newEntityName)));
}
}
tree.freshenParentAndChildIndexes();
}
}
public void replaceOrderBy(PathEntityReference orderingFieldRef, boolean desc) {
CommonTree orderBy = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY);
OrderByFieldNode orderByField;
@ -162,5 +203,15 @@ public class QueryTreeTransformer extends QueryTreeAnalyzer {
return result;
}
protected <T> List<T> getChildrenByClass(CommonTree commonTree, Class<?> clazz) {
List<Object> childrenByClass = new ArrayList<>();
for (Object o : commonTree.getChildren()) {
if (clazz.isAssignableFrom(o.getClass())) {
childrenByClass.add(o);
}
}
return (List<T>) childrenByClass;
}
}

View File

@ -793,6 +793,42 @@ public class QueryTransformerAstBasedTest {
res);
}
@Test
public void testRemoveDistinct() throws RecognitionException {
DomainModel model = prepareDomainModel();
QueryTransformerAstBased transformer = new QueryTransformerAstBased(model,
"select distinct h from sec$GroupHierarchy h", "sec$GroupHierarchy");
transformer.removeDistinct();
String res = transformer.getResult();
assertEquals(
"select h from sec$GroupHierarchy h\", \"sec$GroupHierarchy",
res);
}
@Test
public void testRemoveOrderBy() throws RecognitionException {
DomainModel model = prepareDomainModel();
QueryTransformerAstBased transformer = new QueryTransformerAstBased(model,
"select h from sec$GroupHierarchy h order by h.createdBy", "sec$GroupHierarchy");
transformer.removeOrderBy();
String res = transformer.getResult();
assertEquals(
"select h from sec$GroupHierarchy h",
res);
}
@Test
public void testReplaceName() throws RecognitionException {
DomainModel model = prepareDomainModel();
QueryTransformerAstBased transformer = new QueryTransformerAstBased(model,
"select h from sec$GroupHierarchy h", "sec$GroupHierarchy");
transformer.replaceEntityName("sec$ExtGroupHierarchy");
String res = transformer.getResult();
assertEquals(
"select h from sec$ExtGroupHierarchy h",
res);
}
@Test
public void transformationsUsingSelectedEntity() throws RecognitionException {
EntityBuilder builder = new EntityBuilder();