001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2005-2009 Pentaho and others 008// All Rights Reserved. 009*/ 010package mondrian.olap.fun; 011 012import mondrian.calc.*; 013import mondrian.calc.impl.GenericCalc; 014import mondrian.calc.impl.GenericIterCalc; 015import mondrian.mdx.ResolvedFunCall; 016import mondrian.olap.*; 017import mondrian.olap.type.SetType; 018import mondrian.olap.type.Type; 019 020import java.io.PrintWriter; 021import java.util.List; 022 023/** 024 * Definition of the <code>Cache</code> system function, which is smart enough 025 * to evaluate its argument only once. 026 * 027 * @author jhyde 028 * @since 2005/8/14 029 */ 030public class CacheFunDef extends FunDefBase { 031 static final String NAME = "Cache"; 032 private static final String SIGNATURE = "Cache(<<Exp>>)"; 033 private static final String DESCRIPTION = 034 "Evaluates and returns its sole argument, applying statement-level caching"; 035 private static final Syntax SYNTAX = Syntax.Function; 036 static final CacheFunResolver Resolver = new CacheFunResolver(); 037 038 CacheFunDef( 039 String name, 040 String signature, 041 String description, 042 Syntax syntax, 043 int category, 044 Type type) 045 { 046 super( 047 name, signature, description, syntax, 048 category, new int[] {category}); 049 Util.discard(type); 050 } 051 052 public void unparse(Exp[] args, PrintWriter pw) { 053 args[0].unparse(pw); 054 } 055 056 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 057 final Exp exp = call.getArg(0); 058 final ExpCacheDescriptor cacheDescriptor = 059 new ExpCacheDescriptor(exp, compiler); 060 if (call.getType() instanceof SetType) { 061 return new GenericIterCalc(call) { 062 public Object evaluate(Evaluator evaluator) { 063 return evaluator.getCachedResult(cacheDescriptor); 064 } 065 066 public Calc[] getCalcs() { 067 return new Calc[] {cacheDescriptor.getCalc()}; 068 } 069 070 public ResultStyle getResultStyle() { 071 // cached lists are immutable 072 return ResultStyle.LIST; 073 } 074 }; 075 } else { 076 return new GenericCalc(call) { 077 public Object evaluate(Evaluator evaluator) { 078 return evaluator.getCachedResult(cacheDescriptor); 079 } 080 081 public Calc[] getCalcs() { 082 return new Calc[] {cacheDescriptor.getCalc()}; 083 } 084 085 public ResultStyle getResultStyle() { 086 return ResultStyle.VALUE; 087 } 088 }; 089 } 090 } 091 092 public static class CacheFunResolver extends ResolverBase { 093 CacheFunResolver() { 094 super(NAME, SIGNATURE, DESCRIPTION, SYNTAX); 095 } 096 097 public FunDef resolve( 098 Exp[] args, 099 Validator validator, 100 List<Conversion> conversions) 101 { 102 if (args.length != 1) { 103 return null; 104 } 105 final Exp exp = args[0]; 106 final int category = exp.getCategory(); 107 final Type type = exp.getType(); 108 return new CacheFunDef( 109 NAME, SIGNATURE, DESCRIPTION, SYNTAX, 110 category, type); 111 } 112 113 public boolean requiresExpression(int k) { 114 return false; 115 } 116 } 117} 118 119// End CacheFunDef.java