Skip to content

Commit

Permalink
TEIID-2736: 1) Fixed the bug with nested function expressions 2) adde…
Browse files Browse the repository at this point in the history
…d support for boolean expressions in select clause using mongodb's operator
  • Loading branch information
rareddy committed Nov 15, 2013
1 parent 61d144f commit bd60175
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 72 deletions.
Expand Up @@ -281,6 +281,11 @@ public boolean supportsSelectExpression() {
return true;
}

@Override
public boolean supportsOnlyLiteralComparison() {
return true;
}

/**
* @param field
* @param expectedClass
Expand Down
Expand Up @@ -58,7 +58,6 @@ public class MongoDBSelectVisitor extends HierarchyVisitor {
private Select command;
protected ArrayList<TranslatorException> exceptions = new ArrayList<TranslatorException>();

protected Stack<DBObject> onGoingCriteria = new Stack<DBObject>();
protected Stack<DBObject> onGoingPullCriteria = new Stack<DBObject>();
protected Stack<Object> onGoingExpression = new Stack<Object>();
protected ConcurrentHashMap<Object, ColumnAlias> expressionMap = new ConcurrentHashMap<Object, ColumnAlias>();
Expand All @@ -80,6 +79,7 @@ public class MongoDBSelectVisitor extends HierarchyVisitor {
protected LinkedList<String> unwindTables = new LinkedList<String>();
protected ArrayList<Condition> pendingConditions = new ArrayList<Condition>();
protected LinkedList<MongoDocument> joinedDocuments = new LinkedList<MongoDocument>();
private boolean processingDerivedColumn = false;

public MongoDBSelectVisitor(MongoDBExecutionFactory executionFactory, RuntimeMetadata metadata) {
this.executionFactory = executionFactory;
Expand Down Expand Up @@ -146,7 +146,12 @@ public String getColumnName(ColumnReference obj) {
@Override
public void visit(DerivedColumn obj) {
this.onGoingAlias = buildAlias(obj.getAlias());
append(obj.getExpression());

Expression originalExpr = obj.getExpression();

this.processingDerivedColumn = true;
append(originalExpr);
this.processingDerivedColumn = false;

Object expr = this.onGoingExpression.pop();

Expand All @@ -155,7 +160,7 @@ public void visit(DerivedColumn obj) {
previousAlias = this.onGoingAlias;
}

if (obj.getExpression() instanceof ColumnReference) {
if (originalExpr instanceof ColumnReference) {
String elementName = getColumnName((ColumnReference)obj.getExpression());
this.selectColumnReferences.add(elementName);
// the the expression is already part of group by then the projection should be $_id.{name}
Expand All @@ -179,6 +184,23 @@ public void visit(DerivedColumn obj) {
}
}
else {
if (originalExpr instanceof AggregateFunction) {
ColumnAlias alias = addToProject(expr, false);
if (!this.group.values().contains(expr)) {
this.group.put(alias.projectedName, expr);
}
}
else if (originalExpr instanceof Function) {
addToProject(expr, true);
}
else if (originalExpr instanceof Condition) {
// needs to be in the form "_mo: {$cond: [{$eq :["$city", "FREEDOM"]}, true, false]}}}"
BasicDBList values = new BasicDBList();
values.add(0, expr);
values.add(1, true);
values.add(2, false);
addToProject(new BasicDBObject("$cond", values), true); //$NON-NLS-1$
}
// what user sees as project
this.selectColumns.add(previousAlias.projectedName);
this.selectColumnReferences.add(previousAlias.projectedName);
Expand Down Expand Up @@ -327,15 +349,11 @@ else if (obj.getName().equals(AggregateFunction.MAX)) {
}

if (expr != null) {
ColumnAlias alias = addToProject(expr, false);
if (!this.group.values().contains(expr)) {
this.group.put(alias.projectedName, expr);
}
this.onGoingExpression.push(expr);
}
}

private ColumnAlias addToProject(BasicDBObject expr, boolean addExprAsProject) {
private ColumnAlias addToProject(Object expr, boolean addExprAsProject) {
ColumnAlias previousAlias = this.expressionMap.get(expr);
if (previousAlias == null) {
// if expression is in having clause there is will be no alias; however mongo expects this
Expand Down Expand Up @@ -371,8 +389,7 @@ public void visit(Function obj) {
expr = new BasicDBObject(obj.getName(), params);
}

if(expr != null) {
addToProject(expr, true);
if(expr != null) {
this.onGoingExpression.push(expr);
}
}
Expand Down Expand Up @@ -472,12 +489,12 @@ public void visit(Select obj) {
append(obj.getWhere());
}

if (!this.onGoingCriteria.isEmpty()) {
if (!this.onGoingExpression.isEmpty()) {
if (this.match != null) {
this.match = QueryBuilder.start().and(this.match, this.onGoingCriteria.pop()).get();
this.match = QueryBuilder.start().and(this.match, (DBObject)this.onGoingExpression.pop()).get();
}
else {
this.match = this.onGoingCriteria.pop();
this.match = (DBObject)this.onGoingExpression.pop();
}
}

Expand All @@ -498,8 +515,8 @@ public void visit(Select obj) {
append(obj.getHaving());
}

if (!this.onGoingCriteria.isEmpty()) {
this.having = this.onGoingCriteria.pop();
if (!this.onGoingExpression.isEmpty()) {
this.having = (DBObject)this.onGoingExpression.pop();
}

if (!this.group.isEmpty()) {
Expand All @@ -522,46 +539,54 @@ public void visit(Select obj) {

@Override
public void visit(Comparison obj) {

// this for $cond in the select statement, and formatting of command for $cond vs $match is different
if (this.processingDerivedColumn) {
visitDerivedExpression(obj);
return;
}

// this for the normal where clause
ColumnAlias exprAlias = getExpressionAlias(obj.getLeftExpression());
QueryBuilder query = QueryBuilder.start(exprAlias.selectionName);
QueryBuilder pullQuery = QueryBuilder.start(exprAlias.pullColumnName);

append(obj.getRightExpression());

Object rightExpr = this.onGoingExpression.pop();
if (this.expressionMap.get(rightExpr) != null) {
rightExpr = this.expressionMap.get(rightExpr).projectedName;
}
if (query != null) {
switch(obj.getOperator()) {
case EQ:
query.is(rightExpr);
pullQuery.is(rightExpr);
break;
case NE:
query.notEquals(rightExpr);
pullQuery.notEquals(rightExpr);
break;
case LT:
query.lessThan(rightExpr);
pullQuery.lessThan(rightExpr);
break;
case LE:
query.lessThanEquals(rightExpr);
pullQuery.lessThanEquals(rightExpr);
break;
case GT:
query.greaterThan(rightExpr);
pullQuery.greaterThan(rightExpr);
break;
case GE:
query.greaterThanEquals(rightExpr);
pullQuery.greaterThanEquals(rightExpr);
break;
}
this.onGoingCriteria.push(query.get());

QueryBuilder query = QueryBuilder.start(exprAlias.selectionName);
QueryBuilder pullQuery = QueryBuilder.start(exprAlias.pullColumnName);

switch(obj.getOperator()) {
case EQ:
query.is(rightExpr);
pullQuery.is(rightExpr);
break;
case NE:
query.notEquals(rightExpr);
pullQuery.notEquals(rightExpr);
break;
case LT:
query.lessThan(rightExpr);
pullQuery.lessThan(rightExpr);
break;
case LE:
query.lessThanEquals(rightExpr);
pullQuery.lessThanEquals(rightExpr);
break;
case GT:
query.greaterThan(rightExpr);
pullQuery.greaterThan(rightExpr);
break;
case GE:
query.greaterThanEquals(rightExpr);
pullQuery.greaterThanEquals(rightExpr);
break;
}

this.onGoingExpression.push(query.get());

if (obj.getLeftExpression() instanceof ColumnReference) {
ColumnReference colum = (ColumnReference)obj.getLeftExpression();
this.mongoDoc.updateReferenceColumnValue(colum.getTable().getName(), exprAlias.columnName, rightExpr);
Expand All @@ -571,23 +596,61 @@ public void visit(Comparison obj) {
this.onGoingPullCriteria.push(pullQuery.get());
}

private void visitDerivedExpression(Comparison obj) {
append(obj.getLeftExpression());
Object leftExpr = this.onGoingExpression.pop();
append(obj.getRightExpression());
Object rightExpr = this.onGoingExpression.pop();

BasicDBList values = new BasicDBList();
values.add(0, leftExpr);
values.add(1, rightExpr);

switch(obj.getOperator()) {
case EQ:
this.onGoingExpression.push(new BasicDBObject("$eq", values)); //$NON-NLS-1$
this.onGoingPullCriteria.push(new BasicDBObject("$eq", values)); //$NON-NLS-1$
break;
case NE:
this.onGoingExpression.push(new BasicDBObject("$ne", values)); //$NON-NLS-1$
this.onGoingPullCriteria.push(new BasicDBObject("$ne", values)); //$NON-NLS-1$
break;
case LT:
this.onGoingExpression.push(new BasicDBObject("$lt", values)); //$NON-NLS-1$
this.onGoingPullCriteria.push(new BasicDBObject("$lt", values)); //$NON-NLS-1$
break;
case LE:
this.onGoingExpression.push(new BasicDBObject("$lte", values)); //$NON-NLS-1$
this.onGoingPullCriteria.push(new BasicDBObject("$lte", values)); //$NON-NLS-1$
break;
case GT:
this.onGoingExpression.push(new BasicDBObject("$gt", values)); //$NON-NLS-1$
this.onGoingPullCriteria.push(new BasicDBObject("$gt", values)); //$NON-NLS-1$
break;
case GE:
this.onGoingExpression.push(new BasicDBObject("$gte", values)); //$NON-NLS-1$
this.onGoingPullCriteria.push(new BasicDBObject("$gte", values)); //$NON-NLS-1$
break;
}
}

@Override
public void visit(AndOr obj) {
append(obj.getLeftCondition());
append(obj.getRightCondition());
DBObject right = this.onGoingCriteria.pop();
DBObject left = this.onGoingCriteria.pop();
DBObject right = (DBObject)this.onGoingExpression.pop();
DBObject left = (DBObject) this.onGoingExpression.pop();

DBObject pullRight = this.onGoingPullCriteria.pop();
DBObject pullLeft = this.onGoingPullCriteria.pop();

switch(obj.getOperator()) {
case AND:
this.onGoingCriteria.push(QueryBuilder.start().and(left, right).get());
this.onGoingExpression.push(QueryBuilder.start().and(left, right).get());
this.onGoingPullCriteria.push(QueryBuilder.start().and(pullLeft, pullRight).get());
break;
case OR:
this.onGoingCriteria.push(QueryBuilder.start().or(left, right).get());
this.onGoingExpression.push(QueryBuilder.start().or(left, right).get());
this.onGoingPullCriteria.push(QueryBuilder.start().or(pullLeft, pullRight).get());
break;
}
Expand Down Expand Up @@ -623,7 +686,7 @@ public void visit(In obj) {
query.in(values);
pullQuery.in(values);
}
this.onGoingCriteria.push(query.get());
this.onGoingExpression.push(query.get());
this.onGoingPullCriteria.push(pullQuery.get());
}
}
Expand All @@ -637,8 +700,8 @@ private ColumnAlias getExpressionAlias(Expression obj) {
Object expr = this.onGoingExpression.pop();
ColumnAlias exprAlias = this.expressionMap.get(expr);
if (exprAlias == null) {
//exprAlias = buildAlias(null);
//this.expressionMap.put(expr, exprAlias);
exprAlias = buildAlias(null);
this.expressionMap.put(expr, exprAlias);
}

// when expression shows up in a condition, but it is not a derived column
Expand All @@ -661,7 +724,7 @@ public void visit(IsNull obj) {
query.is(null);
pullQuery.is(null);
}
this.onGoingCriteria.push(query.get());
this.onGoingExpression.push(query.get());
this.onGoingPullCriteria.push(pullQuery.get());
}
}
Expand Down Expand Up @@ -709,7 +772,7 @@ public void visit(Like obj) {
String regex = value.toString().replaceAll("%", ""); //$NON-NLS-1$ //$NON-NLS-2$
query.is(Pattern.compile(regex));
pullQuery.is(Pattern.compile(regex));
this.onGoingCriteria.push(query.get());
this.onGoingExpression.push(query.get());
this.onGoingPullCriteria.push(pullQuery.get());
}
}
Expand Down
Expand Up @@ -110,8 +110,8 @@ public void visit(Update obj) {

append(obj.getWhere());

if (!this.onGoingCriteria.isEmpty()) {
this.match = this.onGoingCriteria.pop();
if (!this.onGoingExpression.isEmpty()) {
this.match = (DBObject)this.onGoingExpression.pop();
}
}

Expand All @@ -121,8 +121,8 @@ public void visit(Delete obj) {
append(obj.getTable());
append(obj.getWhere());

if (!this.onGoingCriteria.isEmpty()) {
this.match = this.onGoingCriteria.pop();
if (!this.onGoingExpression.isEmpty()) {
this.match = (DBObject)this.onGoingExpression.pop();
}
}

Expand Down

0 comments on commit bd60175

Please sign in to comment.