// 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); } } } }