1 9 package mondrian.rolap; 10 11 import java.util.ArrayList ; 12 import java.util.List ; 13 14 import mondrian.olap.*; 15 import mondrian.rolap.sql.SqlQuery; 16 import mondrian.mdx.MemberExpr; 17 18 26 public class RolapNativeSql { 27 28 private SqlQuery sqlQuery; 29 private SqlQuery.Dialect dialect; 30 31 CompositeSqlCompiler numericCompiler; 32 CompositeSqlCompiler booleanCompiler; 33 34 RolapStoredMeasure storedMeasure; 35 36 43 private boolean saveStoredMeasure(RolapStoredMeasure m) { 44 if (storedMeasure != null) { 45 RolapStar star1 = getStar(storedMeasure); 46 RolapStar star2 = getStar(m); 47 if (star1 != star2) 48 return false; 49 } 50 this.storedMeasure = m; 51 return true; 52 } 53 54 private RolapStar getStar(RolapStoredMeasure m) { 55 return ((RolapStar.Measure )m.getStarMeasure()).getStar(); 56 } 57 58 64 interface SqlCompiler { 65 72 String compile(Exp exp); 73 } 74 75 80 class CompositeSqlCompiler implements SqlCompiler { 81 List <SqlCompiler> compilers = new ArrayList <SqlCompiler>(); 82 83 public void add(SqlCompiler compiler) { 84 compilers.add(compiler); 85 } 86 87 public String compile(Exp exp) { 88 for (SqlCompiler compiler : compilers) { 89 String s = compiler.compile(exp); 90 if (s != null) { 91 return s; 92 } 93 } 94 return null; 95 } 96 97 public String toString() { 98 return compilers.toString(); 99 } 100 101 } 102 103 108 class NumberSqlCompiler implements SqlCompiler { 109 public String compile(Exp exp) { 110 if (!(exp instanceof Literal)) { 111 return null; 112 } 113 if ((exp.getCategory() & Category.Numeric) == 0) { 114 return null; 115 } 116 Literal literal = (Literal) exp; 117 String expr = String.valueOf(literal.getValue()); 118 if (dialect.isDB2()) { 119 expr = "FLOAT(" + expr + ")"; 120 } 121 return expr; 122 } 123 124 public String toString() { 125 return "NumberSqlCompiler"; 126 } 127 } 128 129 134 abstract class MemberSqlCompiler implements SqlCompiler { 135 protected Exp unwind(Exp exp) { 136 return exp; 137 } 138 } 139 140 146 class StoredMeasureSqlCompiler extends MemberSqlCompiler { 147 148 public String compile(Exp exp) { 149 exp = unwind(exp); 150 if (!(exp instanceof MemberExpr)) { 151 return null; 152 } 153 final Member member = ((MemberExpr) exp).getMember(); 154 if (!(member instanceof RolapStoredMeasure)) { 155 return null; 156 } 157 RolapStoredMeasure measure = (RolapStoredMeasure) member; 158 if (measure.isCalculated()) { 159 return null; } 161 if (!saveStoredMeasure(measure)) 162 return null; 163 String exprInner = measure.getMondrianDefExpression().getExpression(sqlQuery); 164 String expr = measure.getAggregator().getExpression(exprInner); 165 if (dialect.isDB2()) { 166 expr = "FLOAT(" + expr + ")"; 167 } 168 return expr; 169 } 170 171 public String toString() { 172 return "StoredMeasureSqlCompiler"; 173 } 174 } 175 176 182 class CalculatedMemberSqlCompiler extends MemberSqlCompiler { 183 SqlCompiler compiler; 184 185 CalculatedMemberSqlCompiler(SqlCompiler argumentCompiler) { 186 this.compiler = argumentCompiler; 187 } 188 189 public String compile(Exp exp) { 190 exp = unwind(exp); 191 if (!(exp instanceof MemberExpr)) { 192 return null; 193 } 194 final Member member = ((MemberExpr) exp).getMember(); 195 if (!(member instanceof RolapCalculatedMember)) { 196 return null; 197 } 198 exp = member.getExpression(); 199 if (exp == null) { 200 return null; 201 } 202 return compiler.compile(exp); 203 } 204 205 public String toString() { 206 return "CalculatedMemberSqlCompiler"; 207 } 208 } 209 210 216 abstract class FunCallSqlCompilerBase implements SqlCompiler { 217 int category; 218 String mdx; 219 int argCount; 220 221 FunCallSqlCompilerBase(int category, String mdx, int argCount) { 222 this.category = category; 223 this.mdx = mdx; 224 this.argCount = argCount; 225 } 226 227 230 protected boolean match(Exp exp) { 231 if ((exp.getCategory() & category) == 0) { 232 return false; 233 } 234 if (!(exp instanceof FunCall)) { 235 return false; 236 } 237 FunCall fc = (FunCall) exp; 238 if (!mdx.equalsIgnoreCase(fc.getFunName())) { 239 return false; 240 } 241 Exp[] args = fc.getArgs(); 242 if (args.length != argCount) { 243 return false; 244 } 245 return true; 246 } 247 248 254 protected String [] compileArgs(Exp exp, SqlCompiler compiler) { 255 if (!match(exp)) { 256 return null; 257 } 258 Exp[] args = ((FunCall) exp).getArgs(); 259 String [] sqls = new String [args.length]; 260 for (int i = 0; i < args.length; i++) { 261 sqls[i] = compiler.compile(args[i]); 262 if (sqls[i] == null) { 263 return null; 264 } 265 } 266 return sqls; 267 } 268 } 269 270 275 class FunCallSqlCompiler extends FunCallSqlCompilerBase { 276 SqlCompiler compiler; 277 String sql; 278 279 protected FunCallSqlCompiler(int category, String mdx, String sql, 280 int argCount, SqlCompiler argumentCompiler) { 281 super(category, mdx, argCount); 282 this.sql = sql; 283 this.compiler = argumentCompiler; 284 } 285 286 public String compile(Exp exp) { 287 String [] args = compileArgs(exp, compiler); 288 if (args == null) { 289 return null; 290 } 291 StringBuilder buf = new StringBuilder (); 292 buf.append(sql); 293 buf.append("("); 294 for (int i = 0; i < args.length; i++) { 295 if (i > 0) { 296 buf.append(", "); 297 } 298 buf.append(args[i]); 299 } 300 buf.append(") "); 301 return buf.toString(); 302 } 303 304 public String toString() { 305 return "FunCallSqlCompiler[" + mdx + "]"; 306 } 307 } 308 309 314 class UnaryOpSqlCompiler extends FunCallSqlCompiler { 315 protected UnaryOpSqlCompiler(int category, String mdx, String sql, SqlCompiler argumentCompiler) { 316 super(category, mdx, sql, 1, argumentCompiler); 317 } 318 } 319 320 325 class ParenthesisSqlCompiler extends FunCallSqlCompiler { 326 protected ParenthesisSqlCompiler(int category, SqlCompiler argumentCompiler) { 327 super(category, "()", "", 1, argumentCompiler); 328 } 329 330 public String toString() { 331 return "ParenthesisSqlCompiler"; 332 } 333 } 334 335 341 class InfixOpSqlCompiler extends FunCallSqlCompilerBase { 342 private final String sql; 343 private final SqlCompiler compiler; 344 345 protected InfixOpSqlCompiler(int category, String mdx, String sql, 346 SqlCompiler argumentCompiler) { 347 super(category, mdx, 2); 348 this.sql = sql; 349 this.compiler = argumentCompiler; 350 } 351 352 public String compile(Exp exp) { 353 String [] args = compileArgs(exp, compiler); 354 if (args == null) { 355 return null; 356 } 357 return "(" + args[0] + " " + sql + " " + args[1] + ")"; 358 } 359 360 public String toString() { 361 return "InfixSqlCompiler[" + mdx + "]"; 362 } 363 } 364 365 372 class IifSqlCompiler extends FunCallSqlCompilerBase { 373 374 SqlCompiler valueCompiler; 375 376 IifSqlCompiler(int category, SqlCompiler valueCompiler) { 377 super(category, "iif", 3); 378 this.valueCompiler = valueCompiler; 379 } 380 381 public String compile(Exp exp) { 382 if (!match(exp)) { 383 return null; 384 } 385 Exp[] args = ((FunCall) exp).getArgs(); 386 String cond = booleanCompiler.compile(args[0]); 387 String val1 = valueCompiler.compile(args[1]); 388 String val2 = valueCompiler.compile(args[2]); 389 if (cond == null || val1 == null || val2 == null) { 390 return null; 391 } 392 return sqlQuery.getDialect().caseWhenElse(cond, val1, val2); 393 } 394 395 } 396 397 401 RolapNativeSql(SqlQuery sqlQuery) { 402 this.sqlQuery = sqlQuery; 403 this.dialect = sqlQuery.getDialect(); 404 405 numericCompiler = new CompositeSqlCompiler(); 406 booleanCompiler = new CompositeSqlCompiler(); 407 408 numericCompiler.add(new NumberSqlCompiler()); 409 numericCompiler.add(new StoredMeasureSqlCompiler()); 410 numericCompiler.add(new CalculatedMemberSqlCompiler(numericCompiler)); 411 numericCompiler.add(new ParenthesisSqlCompiler(Category.Numeric, numericCompiler)); 412 numericCompiler.add(new InfixOpSqlCompiler(Category.Numeric, "+", "+", numericCompiler)); 413 numericCompiler.add(new InfixOpSqlCompiler(Category.Numeric, "-", "-", numericCompiler)); 414 numericCompiler.add(new InfixOpSqlCompiler(Category.Numeric, "/", "/", numericCompiler)); 415 numericCompiler.add(new InfixOpSqlCompiler(Category.Numeric, "*", "*", numericCompiler)); 416 numericCompiler.add(new IifSqlCompiler(Category.Numeric, numericCompiler)); 417 418 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, "<", "<", numericCompiler)); 419 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, "<=", "<=", numericCompiler)); 420 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, ">", ">", numericCompiler)); 421 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, ">=", ">=", numericCompiler)); 422 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, "=", "=", numericCompiler)); 423 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, "<>", "<>", numericCompiler)); 424 425 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, "and", "AND", booleanCompiler)); 426 booleanCompiler.add(new InfixOpSqlCompiler(Category.Logical, "or", "OR", booleanCompiler)); 427 booleanCompiler.add(new UnaryOpSqlCompiler(Category.Logical, "not", "NOT", booleanCompiler)); 428 booleanCompiler.add(new ParenthesisSqlCompiler(Category.Logical, booleanCompiler)); 429 booleanCompiler.add(new IifSqlCompiler(Category.Logical, booleanCompiler)); 430 } 431 432 436 public String generateTopCountOrderBy(Exp exp) { 437 return numericCompiler.compile(exp); 438 } 439 440 public String generateFilterCondition(Exp exp) { 441 return booleanCompiler.compile(exp); 442 } 443 444 public RolapStoredMeasure getStoredMeasure() { 445 return storedMeasure; 446 } 447 448 } 449 450 | Popular Tags |