package com.tesora.dve.sql.node.expression; /* * #%L * Tesora Inc. * Database Virtualization Engine * %% * Copyright (C) 2011 - 2014 Tesora Inc. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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/>. * #L% */ import com.tesora.dve.sql.SchemaException; import com.tesora.dve.sql.ParserException.Pass; import com.tesora.dve.sql.node.LanguageNode; import com.tesora.dve.sql.schema.ConnectionValues; import com.tesora.dve.sql.schema.cache.IConstantExpression; import com.tesora.dve.sql.schema.cache.ILateEvalLiteralExpression; import com.tesora.dve.sql.schema.cache.ILiteralExpression; import com.tesora.dve.sql.transform.CopyContext; public class LateEvaluatingLiteralExpression extends DelegatingLiteralExpression implements ILateEvalLiteralExpression { private final LateEvaluator evaluator; private final ConstantExpression[] params; public LateEvaluatingLiteralExpression(int literalType, ConstantExpression[] parameters, LateEvaluator eval) { super(literalType,null,null,0,null,true); evaluator = eval; params = parameters; if (params.length != evaluator.getParamTypes().length) throw new SchemaException(Pass.PLANNER, "LateEvaluatingLiteralExpression: expect " + evaluator.getParamTypes().length + " params but have " + params.length); } @Override protected LanguageNode copySelf(CopyContext cc) { ConstantExpression[] np = new ConstantExpression[params.length]; for(int i = 0; i < params.length; i++) np[i] = (ConstantExpression) params[i].copy(cc); LateEvaluatingLiteralExpression out = new LateEvaluatingLiteralExpression(getValueType(),np,evaluator); return out; } @Override public Object getValue(ConnectionValues cv) { IConstantExpression[] vals = new IConstantExpression[params.length]; for(int i = 0; i < params.length; i++) vals[i] = params[i]; return evaluator.getValue(cv, vals); } public static abstract class LateEvaluator { private final Class<?>[] paramTypes; public LateEvaluator(Class<?>[] expected) { this.paramTypes = expected; } public Class<?>[] getParamTypes() { return paramTypes; } public abstract Object compute(Object[] in); public Object getValue(ConnectionValues cv, IConstantExpression[] params) { Object[] converted = new Object[params.length]; for(int i = 0; i < paramTypes.length; i++) { Object v = params[i].getValue(cv); converted[i] = convert(v,paramTypes[i]); } return compute(converted); } protected Object convert(Object in, Class<?> c) { if (c.isInstance(in)) return in; if (Number.class.isAssignableFrom(c)) { if (in instanceof Number) { Number n = (Number) in; if (Long.class.equals(c)) { return Long.valueOf(n.longValue()); } else if (Integer.class.equals(c)) { return Integer.valueOf(n.intValue()); } } else if (in instanceof String) { String s = (String) in; if (Long.class.equals(c)) { return Long.valueOf(s); } else if (Integer.class.equals(c)) { return Integer.valueOf(s); } } } throw new SchemaException(Pass.PLANNER, "Fill me in: conversion from " + in.getClass().getSimpleName() + " to " + c.getSimpleName() + " in LateEvaluatingLiteralExpression"); } } public static final LateEvaluator SUM = new LateEvaluator(new Class<?>[] { Long.class, Long.class }) { @Override public Object compute(Object[] in) { Long l = (Long) in[0]; Long r = (Long) in[1]; return new Long(l.longValue() + r.longValue()); } }; @Override public ILiteralExpression getCacheExpression() { IConstantExpression[] cacheParams = new IConstantExpression[params.length]; for(int i = 0; i < cacheParams.length; i++) { cacheParams[i] = params[i].getCacheExpression(); } return new CachedLateEvaluatingLiteralExpression(getValueType(),evaluator,cacheParams); } @Override public int getPosition() { return 0; } }