// When candidate table does not have the field, this method checks
 // if the field can be reached through reference,
 // if yes adds the ref usage and returns to true, if not returns false.
 boolean addRefUsage(CandidateTable table, String col, String srcTbl) throws LensException {
   // available as referenced col
   if (referencedCols.containsKey(col)) {
     for (ReferencedQueriedColumn refer : referencedCols.get(col)) {
       if (refer.srcTable.getName().equalsIgnoreCase(srcTbl)) {
         // check if reference source column is available in src table?
         // should not be required here. Join resolution will figure out if
         // there is no path
         // to the source table
         log.info("Adding denormalized column for column:{} for table:{}", col, table);
         Set<ReferencedQueriedColumn> refCols = tableToRefCols.get(table.getName());
         if (refCols == null) {
           refCols = new HashSet<>();
           tableToRefCols.put(table.getName(), refCols);
         }
         refCols.add(refer);
         // Add to optional tables
         for (ChainRefCol refCol : refer.col.getChainRefColumns()) {
           cubeql.addOptionalDimTable(
               refCol.getChainName(),
               table,
               false,
               refer.col.getName(),
               true,
               refCol.getRefColumn());
         }
         return true;
       }
     }
   }
   return false;
 }
 // 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);
       }
     }
   }
 }
 private void pickExpressionsForTable(CandidateTable cTable) {
   for (Map.Entry<String, Set<ExpressionContext>> ecEntry : allExprsQueried.entrySet()) {
     Set<ExpressionContext> ecSet = ecEntry.getValue();
     for (ExpressionContext ec : ecSet) {
       if (ec.getSrcTable().getName().equals(cTable.getBaseTable().getName())) {
         if (!ec.directlyAvailableIn.contains(cTable)) {
           if (ec.evaluableExpressions.get(cTable) != null
               && !ec.evaluableExpressions.get(cTable).isEmpty()) {
             // pick first evaluable expression
             Set<PickedExpression> peSet = pickedExpressions.get(ecEntry.getKey());
             if (peSet == null) {
               peSet = new HashSet<PickedExpression>();
               pickedExpressions.put(ecEntry.getKey(), peSet);
             }
             peSet.add(
                 new PickedExpression(
                     ec.srcAlias, ec.evaluableExpressions.get(cTable).iterator().next()));
           }
         }
       }
     }
   }
 }
 // checks if expr is evaluable
 public boolean isEvaluable(String expr, CandidateTable cTable) {
   ExpressionContext ec =
       getExpressionContext(expr, cubeql.getAliasForTableName(cTable.getBaseTable().getName()));
   return ec.isEvaluable(cTable);
 }