package org.yamcs.yarch.streamsql; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.yamcs.yarch.CompiledExpression; import org.yamcs.yarch.DataType; import org.yamcs.yarch.DbReaderStream; import org.yamcs.yarch.streamsql.ColumnExpression; import org.yamcs.yarch.streamsql.Expression; import org.yamcs.yarch.streamsql.IncompatibilityException; import org.yamcs.yarch.streamsql.ParseException; import org.yamcs.yarch.streamsql.StreamSqlException; import org.yamcs.yarch.streamsql.ValueExpression; public class InExpression extends Expression { static AtomicInteger at=new AtomicInteger(); private int count=at.incrementAndGet(); public InExpression(Expression expr, List<Expression> list) throws ParseException { super(getChildren(expr,list)); } private static Expression[] getChildren(Expression expr, List<Expression> list) { Expression[] c=new Expression[list.size()+1]; c[0]=expr; int i=1; for(Expression e:list) c[i++]=e; return c; } @Override public Expression addFilter(DbReaderStream tableStream) throws StreamSqlException { if(!(children[0] instanceof ColumnExpression)) { return this; } for(int i=1; i<children.length;i++) { if(!children[1].isConstant()) return this; } ColumnExpression cexpr=(ColumnExpression) children[0]; Set<Object> values=new HashSet<Object>(); for(int i=1; i<children.length;i++) { Object cvalue; if(children[1] instanceof ValueExpression) { cvalue=((ValueExpression)children[i]).value; } else { CompiledExpression compexpr=children[i].compile(); cvalue=compexpr.getValue(null); } values.add(cvalue); } if(tableStream.addInFilter(cexpr,values)) return null; else return this; } @Override protected void doBind() throws StreamSqlException { for(int i=1;i<children.length;i++) { if(!DataType.compatible(children[i].getType(), children[0].getType())) { throw new IncompatibilityException(children[i]+" is of different type than "+children[0]+"("+children[i].getType()+" versus "+children[0].getType()+")"); } } type=DataType.BOOLEAN; } @Override protected void fillCode_Declarations(StringBuilder code) { code.append("\tjava.util.Set inSet"+count+"=new java.util.HashSet();\n"); } @Override protected void fillCode_Constructor(StringBuilder code) throws StreamSqlException { for(int i=1;i<children.length;i++) { if(children[i].isConstant()) { code.append("\t\tinSet"+count+".add("); children[i].fillCode_getValueReturn(code); code.append(");\n"); } } } @Override protected void fillCode_getValueBody(StringBuilder code) throws StreamSqlException{ for(int i=1;i<children.length;i++) { if(!children[i].isConstant()) { code.append("\t\tinSet"+count+".add("); children[i].fillCode_getValueReturn(code); code.append(");\n"); } } } @Override public void fillCode_getValueReturn(StringBuilder code) throws StreamSqlException { code.append("inSet"+count+".contains("); children[0].fillCode_getValueReturn(code); code.append(")"); } @Override public String toString() { StringBuilder sb=new StringBuilder(); sb.append(children[0]).append(" IN ("); boolean first=true; for(int i=1;i<children.length;i++) { if(!first)sb.append(", "); else first=false; sb.append(children[i].toString()); } sb.append(")"); return sb.toString(); } }