package edu.washington.escience.myria.operator.agg; import java.util.List; import edu.washington.escience.myria.DbException; import edu.washington.escience.myria.Schema; import edu.washington.escience.myria.expression.evaluate.GenericEvaluator; import edu.washington.escience.myria.expression.evaluate.PythonUDFEvaluator; import edu.washington.escience.myria.storage.MutableTupleBuffer; import edu.washington.escience.myria.storage.TupleBatch; /** * Apply operator that has to be initialized and carries a state while new tuples are generated. */ public class UserDefinedAggregator implements Aggregator { /** Required for Java serialization. */ private static final long serialVersionUID = 1L; /** logger for this class. */ private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(UserDefinedAggregator.class); /** Evaluators that initialize the state. */ protected final List<GenericEvaluator> initEvaluators; /** Evaluators that update the {@link #state}. One evaluator for each expression in {@link #updateExpressions}. */ protected final List<GenericEvaluator> updateEvaluators; /** The Schema of the state. */ private final Schema stateSchema; /** * @param initEvaluators initialize the state * @param updateEvaluators updates the state given an input row * @param pyUpdateEvaluators for python expression evaluation. * @param emitEvaluators the evaluators that finalize the state * @param resultSchema the schema of the tuples produced by this aggregator * @param stateSchema the schema of the state */ public UserDefinedAggregator( final List<GenericEvaluator> initEvaluators, final List<GenericEvaluator> updateEvaluators, final Schema resultSchema, final Schema stateSchema) { this.initEvaluators = initEvaluators; this.updateEvaluators = updateEvaluators; this.stateSchema = stateSchema; } @Override public int getStateSize() { return stateSchema.numColumns(); } @Override public void addRow( TupleBatch input, int inputRow, MutableTupleBuffer state, int stateRow, final int offset) throws DbException { for (GenericEvaluator eval : updateEvaluators) { eval.updateState(input, inputRow, state, stateRow, offset); } } @Override public void initState(final MutableTupleBuffer state, final int offset) throws DbException { for (GenericEvaluator eval : initEvaluators) { eval.updateState(null, 0, state, 0, offset); } } /** * @param tb * @param offset * @throws DbException */ public void finalizePythonUpdaters(final MutableTupleBuffer tb, final int offset) throws DbException { for (int i = 0; i < updateEvaluators.size(); ++i) { GenericEvaluator eval = updateEvaluators.get(i); if (eval instanceof PythonUDFEvaluator) { ((PythonUDFEvaluator) eval).evalGroups(tb, offset + i); } } } }