package org.yamcs.yarch.streamsql; import java.math.BigDecimal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yamcs.yarch.AbstractStream; import org.yamcs.yarch.ColumnDefinition; import org.yamcs.yarch.DataType; import org.yamcs.yarch.HistogramReaderStream; import org.yamcs.yarch.Stream; import org.yamcs.yarch.TableDefinition; import org.yamcs.yarch.TupleDefinition; import org.yamcs.yarch.YarchDatabase; import org.yamcs.yarch.YarchException; import org.yamcs.yarch.streamsql.StreamSqlException.ErrCode; /** * A source of tuples. Can be: * - a reference to an existing stream objectName * - a reference to a table objectName * - a stream expression * @author nm * */ public class TupleSourceExpression { String objectName=null; StreamExpression streamExpression=null; BigDecimal histogramMergeTime=null; //when histoColumn is set, the objectName must be a table having histograms on that column String histoColumn; boolean ascending = true; boolean follow = true; //after binding TupleDefinition definition; static Logger log=LoggerFactory.getLogger(TupleSourceExpression.class.getName()); public TupleSourceExpression(String name) { this.objectName=name; } public TupleSourceExpression(StreamExpression expr) { this.streamExpression=expr; } public void setHistogramColumn(String histoColumn) { this.histoColumn=histoColumn; } void bind(ExecutionContext c) throws StreamSqlException { if(streamExpression!=null) { streamExpression.bind(c); definition=streamExpression.getOutputDefinition(); } else { YarchDatabase dict=YarchDatabase.getInstance(c.getDbName()); TableDefinition tbl=dict.getTable(objectName); if(tbl!=null) { if(histoColumn==null) { definition=tbl.getTupleDefinition(); } else { if(!tbl.hasHistogram()) throw new StreamSqlException(ErrCode.INVALID_HISTOGRAM_COLUMN, "No histogram configured for table "+tbl.getName()); if(!tbl.getHistogramColumns().contains(histoColumn)) throw new StreamSqlException(ErrCode.INVALID_HISTOGRAM_COLUMN, "Histogram is not configured for column "+histoColumn); definition=new TupleDefinition(); definition.addColumn(tbl.getColumnDefinition(histoColumn)); definition.addColumn(new ColumnDefinition("first", DataType.TIMESTAMP)); definition.addColumn(new ColumnDefinition("last", DataType.TIMESTAMP)); definition.addColumn(new ColumnDefinition("num", DataType.INT)); } } else { Stream stream=dict.getStream(objectName); if(stream==null) throw new ResourceNotFoundException(objectName); if(histoColumn!=null) throw new StreamSqlException(ErrCode.INVALID_HISTOGRAM_COLUMN, "Cannot specify histogram option when selecting from a stream"); definition=stream.getDefinition(); } } } public void setHistogramMergeTime(BigDecimal mergeTime) { histogramMergeTime=mergeTime; } public void setAscending(boolean ascending) { this.ascending = ascending; } public void setFollow(boolean follow) { this.follow = follow; } AbstractStream execute(ExecutionContext c) throws StreamSqlException { AbstractStream stream; if(streamExpression!=null) { stream=streamExpression.execute(c); } else if (objectName!=null) { YarchDatabase ydb=YarchDatabase.getInstance(c.getDbName()); if(!ascending) follow = false; TableDefinition tbl=ydb.getTable(objectName); if(tbl!=null) { if(histoColumn==null) { stream = ydb.getStorageEngine(tbl).newTableReaderStream(tbl, ascending, follow); } else { HistogramReaderStream histoStream; try { histoStream = new HistogramReaderStream(ydb, tbl, histoColumn, definition); } catch (YarchException e) { throw new StreamSqlException(ErrCode.ERROR, e.getMessage()); } if(histogramMergeTime!=null) { histoStream.setMergeTime(histogramMergeTime.longValue()); } stream=histoStream; } } else { stream=ydb.getStream(objectName); if(stream==null) throw new ResourceNotFoundException(objectName); } } else { throw new NoneSpecifiedException(); } return stream; } TupleDefinition getDefinition() { return definition; } }