/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.server.types.texpressions;
import com.foundationdb.qp.operator.QueryBindings;
import com.foundationdb.qp.operator.QueryContext;
import com.foundationdb.qp.row.Row;
import com.foundationdb.server.explain.*;
import com.foundationdb.server.types.LazyList;
import com.foundationdb.server.types.LazyListBase;
import com.foundationdb.server.types.TExecutionContext;
import com.foundationdb.server.types.TInstance;
import com.foundationdb.server.types.TPreptimeContext;
import com.foundationdb.server.types.TPreptimeValue;
import com.foundationdb.server.types.value.Value;
import com.foundationdb.server.types.value.ValueSource;
import com.foundationdb.util.SparseArray;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public final class TPreparedFunction implements TPreparedExpression {
@Override
public TInstance resultType() {
return resultType;
}
@Override
public TPreptimeValue evaluateConstant(final QueryContext queryContext) {
LazyList<TPreptimeValue> lazyInputs = new LazyListBase<TPreptimeValue>() {
@Override
public TPreptimeValue get(int i) {
return inputs.get(i).evaluateConstant(queryContext);
}
@Override
public int size() {
return inputs.size();
}
};
TPreptimeContext preptimeContext = new TPreptimeContext(inputTypes, resultType, queryContext, preptimeValues);
return overload.evaluateConstant(preptimeContext, lazyInputs);
}
@Override
public TEvaluatableExpression build() {
List<TEvaluatableExpression> children = new ArrayList<>(inputs.size());
for (TPreparedExpression input : inputs)
children.add(input.build());
TExecutionContext executionContext =
new TExecutionContext(preptimeValues,
inputTypes,
resultType,
null,
null, null, null);
return new TEvaluatableFunction(
overload,
resultType,
children,
executionContext);
}
@Override
public CompoundExplainer getExplainer(ExplainContext context)
{
return overload.getExplainer(context, inputs, resultType);
}
@Override
public String toString() {
return overload.toString(inputs, resultType);
}
@Override
public boolean isLiteral() {
return false;
}
public TPreparedFunction(TValidatedScalar overload,
TInstance resultType,
List<? extends TPreparedExpression> inputs)
{
this(overload, resultType, inputs, null);
}
public TPreparedFunction(TValidatedScalar overload,
TInstance resultType,
List<? extends TPreparedExpression> inputs,
SparseArray<Object> preptimeValues)
{
this.overload = overload;
this.resultType = resultType;
this.inputTypes = new ArrayList<>(inputs.size());
for (TPreparedExpression input : inputs) {
inputTypes.add(input.resultType());
}
this.inputs = inputs;
this.preptimeValues = preptimeValues;
}
private final TValidatedScalar overload;
private final TInstance resultType;
private final List<TInstance> inputTypes;
private final List<? extends TPreparedExpression> inputs;
private final SparseArray<Object> preptimeValues;
private static final class TEvaluatableFunction implements TEvaluatableExpression {
@Override
public void with(Row row) {
for (int i = 0, inputsSize = inputs.size(); i < inputsSize; i++) {
TEvaluatableExpression input = inputs.get(i);
input.with(row);
inputValues[i] = null;
}
}
@Override
public void with(QueryContext context) {
this.context.setQueryContext(context);
for (int i = 0, inputsSize = inputs.size(); i < inputsSize; i++) {
TEvaluatableExpression input = inputs.get(i);
input.with(context);
inputValues[i] = null;
}
}
@Override
public void with(QueryBindings bindings) {
for (int i = 0, inputsSize = inputs.size(); i < inputsSize; i++) {
TEvaluatableExpression input = inputs.get(i);
input.with(bindings);
inputValues[i] = null;
}
}
@Override
public ValueSource resultValue() {
return resultValue;
}
@Override
public void evaluate() {
Arrays.fill(inputValues, null);
overload.evaluate(context, evaluations, resultValue);
}
public TEvaluatableFunction(TValidatedScalar overload,
TInstance resultType,
final List<? extends TEvaluatableExpression> inputs,
TExecutionContext context)
{
this.overload = overload;
this.inputs = inputs;
this.inputValues = new ValueSource[inputs.size()];
this.context = context;
resultValue = new Value(resultType);
this.evaluations = new LazyListBase<ValueSource>() {
@Override
public ValueSource get(int i) {
ValueSource value = inputValues[i];
if (value == null) {
TEvaluatableExpression inputExpr = inputs.get(i);
inputExpr.evaluate();
value = inputExpr.resultValue();
inputValues[i] = value;
}
return value;
}
@Override
public int size() {
return inputValues.length;
}
};
}
private final TValidatedScalar overload;
private final ValueSource[] inputValues;
private final List<? extends TEvaluatableExpression> inputs;
private final Value resultValue;
private final TExecutionContext context;
private final LazyList<? extends ValueSource> evaluations;
}
}