// updates all expression specs which are evaluable
 public void updateEvaluables(String expr, CandidateTable cTable) throws SemanticException {
   String alias = cubeql.getAliasForTableName(cTable.getBaseTable().getName());
   ExpressionContext ec = getExpressionContext(expr, alias);
   if (cTable.getColumns().contains(expr)) {
     // expression is directly materialized in candidate table
     ec.addDirectlyAvailable(cTable);
   }
   for (ExprSpecContext esc : ec.allExprs) {
     if (esc.getTblAliasToColumns().get(alias) == null) {
       log.debug("{} = {} is evaluable in {}", expr, esc, cTable);
       ec.addEvaluable(cubeql, cTable, esc);
     } else {
       Set<String> columns = esc.getTblAliasToColumns().get(alias);
       boolean isEvaluable = true;
       for (String col : columns) {
         if (!cTable.getColumns().contains(col.toLowerCase())) {
           if (!cubeql
               .getDeNormCtx()
               .addRefUsage(cTable, col, cTable.getBaseTable().getName())) {
             // check if it is available as reference, if not expression is not evaluable
             log.debug("{} = {} is not evaluable in {}", expr, esc, cTable);
             isEvaluable = false;
             break;
           }
         }
       }
       if (isEvaluable) {
         log.debug("{} = {} is evaluable in {}", expr, esc, cTable);
         ec.addEvaluable(cubeql, cTable, esc);
       }
     }
   }
 }
 void addEvaluable(CubeQueryContext cubeql, CandidateTable cTable, ExprSpecContext esc)
     throws SemanticException {
   Set<ExprSpecContext> evalSet = evaluableExpressions.get(cTable);
   if (evalSet == null) {
     evalSet = new LinkedHashSet<ExprSpecContext>();
     evaluableExpressions.put(cTable, evalSet);
   }
   // add optional dimensions involved in expressions
   for (String table : esc.getTblAliasToColumns().keySet()) {
     try {
       if (!CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(table) && !srcAlias.equals(table)) {
         cubeql.addOptionalExprDimTable(
             table,
             exprCol.getName(),
             srcAlias,
             cTable,
             esc.getTblAliasToColumns().get(table).toArray(new String[0]));
         esc.exprDims.add((Dimension) cubeql.getCubeTableForAlias(table));
       }
     } catch (HiveException e) {
       throw new SemanticException(e);
     }
   }
   evalSet.add(esc);
 }
 public boolean hasMeasures(String expr, CubeInterface cube) {
   String alias = cubeql.getAliasForTableName(cube.getName());
   ExpressionContext ec = getExpressionContext(expr, alias);
   boolean hasMeasures = false;
   for (ExprSpecContext esc : ec.allExprs) {
     if (esc.getTblAliasToColumns().get(alias) != null) {
       for (String cubeCol : esc.getTblAliasToColumns().get(alias)) {
         if (cube.getMeasureByName(cubeCol) != null) {
           hasMeasures = true;
           break;
         }
       }
     }
   }
   ec.hasMeasures = hasMeasures;
   return hasMeasures;
 }
 private void resolveColumnsAndAlias(CubeQueryContext cubeql) throws SemanticException {
   for (ExprSpecContext esc : allExprs) {
     esc.resolveColumns(cubeql);
     esc.replaceAliasInAST(cubeql);
     for (String table : esc.getTblAliasToColumns().keySet()) {
       try {
         if (!CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(table)
             && !srcAlias.equals(table)) {
           cubeql.addOptionalDimTable(
               table,
               null,
               false,
               null,
               false,
               esc.getTblAliasToColumns().get(table).toArray(new String[0]));
           esc.exprDims.add((Dimension) cubeql.getCubeTableForAlias(table));
         }
       } catch (HiveException e) {
         throw new SemanticException(e);
       }
     }
   }
   resolveColumnsAndReplaceAlias(cubeql, allExprs);
 }
 private void resolveColumnsAndReplaceAlias(CubeQueryContext cubeql, Set<ExprSpecContext> exprs)
     throws SemanticException {
   Set<ExprSpecContext> nestedExpressions = new LinkedHashSet<ExprSpecContext>();
   for (ExprSpecContext esc : exprs) {
     for (Map.Entry<String, Set<String>> entry : esc.getTblAliasToColumns().entrySet()) {
       if (entry.getKey().equals(CubeQueryContext.DEFAULT_TABLE)) {
         continue;
       }
       AbstractBaseTable baseTable =
           (AbstractBaseTable) cubeql.getCubeTableForAlias(entry.getKey());
       Set<String> exprCols = new HashSet<String>();
       for (String col : entry.getValue()) {
         // col is an expression
         if (baseTable.getExpressionNames().contains(col)) {
           exprCols.add(col);
         }
       }
       // get all combinations of expression replaced with inner exprs AST.
       addAllNestedExpressions(cubeql, esc, baseTable, nestedExpressions, exprCols);
     }
   }
   for (ExprSpecContext esc : nestedExpressions) {
     esc.resolveColumns(cubeql);
     esc.replaceAliasInAST(cubeql);
     for (String table : esc.getTblAliasToColumns().keySet()) {
       try {
         if (!CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(table)
             && !srcAlias.equals(table)) {
           cubeql.addOptionalDimTable(
               table,
               null,
               false,
               null,
               false,
               esc.getTblAliasToColumns().get(table).toArray(new String[0]));
           esc.exprDims.add((Dimension) cubeql.getCubeTableForAlias(table));
         }
       } catch (HiveException e) {
         throw new SemanticException(e);
       }
     }
   }
   exprs.addAll(nestedExpressions);
 }
 private void addAllNestedExpressions(
     CubeQueryContext cubeql,
     ExprSpecContext baseEsc,
     AbstractBaseTable baseTable,
     Set<ExprSpecContext> nestedExpressions,
     Set<String> exprCols)
     throws SemanticException {
   for (String col : exprCols) {
     Set<ExprSpecContext> replacedExpressions = new LinkedHashSet<ExprSpecContext>();
     for (ExprSpec es : baseTable.getExpressionByName(col).getExpressionSpecs()) {
       ASTNode finalAST = HQLParser.copyAST(baseEsc.getFinalAST());
       replaceColumnInAST(finalAST, col, es.getASTNode());
       ExprSpecContext replacedESC = new ExprSpecContext(baseEsc, es, finalAST, cubeql);
       nestedExpressions.add(replacedESC);
       replacedExpressions.add(replacedESC);
     }
     Set<String> remaining = new LinkedHashSet<String>(exprCols);
     remaining.remove(col);
     for (ExprSpecContext replacedESC : replacedExpressions) {
       addAllNestedExpressions(cubeql, replacedESC, baseTable, nestedExpressions, remaining);
     }
   }
 }
 void pruneExpressions() {
   for (Set<ExpressionContext> ecSet : allExprsQueried.values()) {
     for (ExpressionContext ec : ecSet) {
       Set<ExprSpecContext> removedEsc = new HashSet<ExprSpecContext>();
       for (Iterator<ExprSpecContext> iterator = ec.getAllExprs().iterator();
           iterator.hasNext(); ) {
         ExprSpecContext esc = iterator.next();
         boolean removed = false;
         // Go over expression dims and remove expression involving dimensions for which
         // candidate tables are
         // not there
         for (Dimension exprDim : esc.exprDims) {
           if (cubeql.getCandidateDims().get(exprDim) == null
               || cubeql.getCandidateDims().get(exprDim).isEmpty()) {
             log.info(
                 "Removing expression {} as {} it does not have any candidate tables",
                 esc,
                 exprDim);
             iterator.remove();
             removedEsc.add(esc);
             removed = true;
             break;
           }
         }
         if (removed) {
           continue;
         }
         // remove expressions which are not valid in the timerange queried
         // If an expression is defined as
         // ex = a + b // from t1 to t2;
         // ex = c + d // from t2 to t3
         // With range queried, invalid expressions will be removed
         // If range is including more than one expression, queries can be unioned as an
         // improvement at later time.
         // But for now, they are not eligible expressions
         for (TimeRange range : cubeql.getTimeRanges()) {
           if (!esc.isValidInTimeRange(range)) {
             log.info("Removing expression {} as it is not valid in timerange queried", esc);
             iterator.remove();
             removedEsc.add(esc);
             removed = true;
             break;
           }
         }
         if (removed) {
           continue;
         }
         // Go over expressions and remove expression containing unavailable columns in timerange
         // In the example above,
         // if ex = a +b ; and a is not available in timerange queried, it will be removed.
         for (TimeRange range : cubeql.getTimeRanges()) {
           boolean toRemove = false;
           for (Map.Entry<String, Set<String>> entry : esc.getTblAliasToColumns().entrySet()) {
             if (CubeQueryContext.DEFAULT_TABLE.equalsIgnoreCase(entry.getKey())) {
               continue;
             }
             AbstractBaseTable baseTable =
                 (AbstractBaseTable) cubeql.getCubeTableForAlias(entry.getKey());
             for (String col : entry.getValue()) {
               if (!baseTable.getColumnByName(col).isColumnAvailableInTimeRange(range)) {
                 toRemove = true;
                 break;
               }
             }
             if (toRemove) {
               break;
             }
           }
           if (toRemove) {
             log.info(
                 "Removing expression {} as its columns are unavailable in timerange queried",
                 esc);
             iterator.remove();
             removedEsc.add(esc);
             removed = true;
             break;
           }
         }
       }
       for (Set<ExprSpecContext> evalSet : ec.evaluableExpressions.values()) {
         evalSet.removeAll(removedEsc);
       }
     }
   }
 }