private void replaceReferencedColumns(CandidateFact cfact, boolean replaceFact) throws LensException { QueryAST ast = cubeql; if (replaceFact && (tableToRefCols.get(cfact.getName()) != null && !tableToRefCols.get(cfact.getName()).isEmpty())) { ast = cfact; } resolveClause(cubeql, ast.getSelectAST()); resolveClause(cubeql, ast.getWhereAST()); resolveClause(cubeql, ast.getGroupByAST()); resolveClause(cubeql, ast.getHavingAST()); resolveClause(cubeql, cubeql.getOrderByAST()); }
public Set<Dimension> rewriteDenormctx( CandidateFact cfact, Map<Dimension, CandidateDim> dimsToQuery, boolean replaceFact) throws LensException { Set<Dimension> refTbls = new HashSet<>(); if (!tableToRefCols.isEmpty()) { // pick referenced columns for fact if (cfact != null) { pickColumnsForTable(cfact.getName()); } // pick referenced columns for dimensions if (dimsToQuery != null && !dimsToQuery.isEmpty()) { for (CandidateDim cdim : dimsToQuery.values()) { pickColumnsForTable(cdim.getName()); } } // Replace picked reference in all the base trees replaceReferencedColumns(cfact, replaceFact); // Add the picked references to dimsToQuery for (PickedReference picked : pickedRefs) { if (isPickedFor(picked, cfact, dimsToQuery)) { refTbls.add( (Dimension) cubeql.getCubeTableForAlias(picked.getChainRef().getChainName())); cubeql.addColumnsQueried( picked.getChainRef().getChainName(), picked.getChainRef().getRefColumn()); } } } return refTbls; }
private void addRangeClauses(CandidateFact fact) throws LensException { if (fact != null) { // resolve timerange positions and replace it by corresponding where clause for (TimeRange range : getTimeRanges()) { for (Map.Entry<String, String> entry : fact.getRangeToStorageWhereMap().get(range).entrySet()) { String table = entry.getKey(); String rangeWhere = entry.getValue(); if (!StringUtils.isBlank(rangeWhere)) { ASTNode rangeAST = HQLParser.parseExpr(rangeWhere); range.getParent().setChild(range.getChildIndex(), rangeAST); } fact.getStorgeWhereClauseMap().put(table, getWhereTree()); } } } }
private String getStorageStringWithAlias( CandidateFact fact, Map<Dimension, CandidateDim> dimsToQuery, String alias) { if (cubeTbls.get(alias) instanceof CubeInterface) { return fact.getStorageString(alias); } else { return dimsToQuery.get(cubeTbls.get(alias)).getStorageString(alias); } }
// checks if the reference if picked for facts and dimsToQuery passed private boolean isPickedFor( PickedReference picked, CandidateFact cfact, Map<Dimension, CandidateDim> dimsToQuery) { if (cfact != null && picked.pickedFor.equalsIgnoreCase(cfact.getName())) { return true; } if (dimsToQuery != null) { for (CandidateDim cdim : dimsToQuery.values()) { if (picked.pickedFor.equalsIgnoreCase(cdim.getName())) { return true; } } } return false; }
String getQBFromString(CandidateFact fact, Map<Dimension, CandidateDim> dimsToQuery) throws LensException { String fromString; if (getJoinAST() == null) { if (cube != null) { if (dimensions.size() > 0) { throw new LensException(LensCubeErrorCode.NO_JOIN_CONDITION_AVAILABLE.getLensErrorInfo()); } fromString = fact.getStorageString(getAliasForTableName(cube.getName())); } else { if (dimensions.size() != 1) { throw new LensException(LensCubeErrorCode.NO_JOIN_CONDITION_AVAILABLE.getLensErrorInfo()); } Dimension dim = dimensions.iterator().next(); fromString = dimsToQuery.get(dim).getStorageString(getAliasForTableName(dim.getName())); } } else { StringBuilder builder = new StringBuilder(); getQLString(qb.getQbJoinTree(), builder, fact, dimsToQuery); fromString = builder.toString(); } return fromString; }
/** * Find all de-normalized columns, if these columns are not directly available in candidate * tables, query will be replaced with the corresponding table reference */ @Override public void rewriteContext(CubeQueryContext cubeql) throws LensException { DenormalizationContext denormCtx = cubeql.getDeNormCtx(); if (denormCtx == null) { // Adds all the reference dimensions as eligible for denorm fields denormCtx = new DenormalizationContext(cubeql); cubeql.setDeNormCtx(denormCtx); // add ref columns in cube addRefColsQueried(cubeql, cubeql, denormCtx); // add ref columns from expressions for (Set<ExpressionContext> ecSet : cubeql.getExprCtx().getAllExprsQueried().values()) { for (ExpressionContext ec : ecSet) { for (ExprSpecContext esc : ec.getAllExprs()) { addRefColsQueried(cubeql, esc, denormCtx); } } } } else if (!denormCtx.tableToRefCols.isEmpty()) { // In the second iteration of denorm resolver // candidate tables which require denorm fields and the refernces are no // more valid will be pruned if (cubeql.getCube() != null && !cubeql.getCandidateFacts().isEmpty()) { for (Iterator<CandidateFact> i = cubeql.getCandidateFacts().iterator(); i.hasNext(); ) { CandidateFact cfact = i.next(); if (denormCtx.tableToRefCols.containsKey(cfact.getName())) { for (ReferencedQueriedColumn refcol : denormCtx.tableToRefCols.get(cfact.getName())) { if (denormCtx.getReferencedCols().get(refcol.col.getName()).isEmpty()) { log.info( "Not considering fact table:{} as column {} is not available", cfact, refcol.col); cubeql.addFactPruningMsgs( cfact.fact, CandidateTablePruneCause.columnNotFound(refcol.col.getName())); i.remove(); } } } } if (cubeql.getCandidateFacts().size() == 0) { throw new LensException( LensCubeErrorCode.NO_FACT_HAS_COLUMN.getLensErrorInfo(), cubeql.getColumnsQueried(cubeql.getCube().getName()).toString()); } cubeql.pruneCandidateFactSet(CandidateTablePruneCode.COLUMN_NOT_FOUND); } if (cubeql.getDimensions() != null && !cubeql.getDimensions().isEmpty()) { for (Dimension dim : cubeql.getDimensions()) { for (Iterator<CandidateDim> i = cubeql.getCandidateDimTables().get(dim).iterator(); i.hasNext(); ) { CandidateDim cdim = i.next(); if (denormCtx.tableToRefCols.containsKey(cdim.getName())) { for (ReferencedQueriedColumn refcol : denormCtx.tableToRefCols.get(cdim.getName())) { if (denormCtx.getReferencedCols().get(refcol.col.getName()).isEmpty()) { log.info( "Not considering dim table:{} as column {} is not available", cdim, refcol.col); cubeql.addDimPruningMsgs( dim, cdim.dimtable, CandidateTablePruneCause.columnNotFound(refcol.col.getName())); i.remove(); } } } } if (cubeql.getCandidateDimTables().get(dim).size() == 0) { throw new LensException( LensCubeErrorCode.NO_DIM_HAS_COLUMN.getLensErrorInfo(), dim.toString(), cubeql.getColumnsQueried(dim.getName()).toString()); } } } } }
public String toHQL() throws LensException { Set<CandidateFact> cfacts = pickCandidateFactToQuery(); Map<Dimension, CandidateDim> dimsToQuery = pickCandidateDimsToQuery(dimensions); log.info("facts:{}, dimsToQuery: {}", cfacts, dimsToQuery); if (autoJoinCtx != null) { // prune join paths for picked fact and dimensions autoJoinCtx.pruneAllPaths(cube, cfacts, dimsToQuery); } Map<CandidateFact, Set<Dimension>> factDimMap = new HashMap<>(); if (cfacts != null) { if (cfacts.size() > 1) { // copy ASTs for each fact for (CandidateFact cfact : cfacts) { cfact.copyASTs(this); factDimMap.put(cfact, new HashSet<>(dimsToQuery.keySet())); } } for (CandidateFact fact : cfacts) { addRangeClauses(fact); } } // pick dimension tables required during expression expansion for the picked fact and dimensions Set<Dimension> exprDimensions = new HashSet<Dimension>(); if (cfacts != null) { for (CandidateFact cfact : cfacts) { Set<Dimension> factExprDimTables = exprCtx.rewriteExprCtx(cfact, dimsToQuery, cfacts.size() > 1 ? cfact : this); exprDimensions.addAll(factExprDimTables); if (cfacts.size() > 1) { factDimMap.get(cfact).addAll(factExprDimTables); } } if (cfacts.size() > 1) { havingAST = MultiFactHQLContext.pushDownHaving(havingAST, this, cfacts); } } else { // dim only query exprDimensions.addAll(exprCtx.rewriteExprCtx(null, dimsToQuery, this)); } dimsToQuery.putAll(pickCandidateDimsToQuery(exprDimensions)); log.info("facts:{}, dimsToQuery: {}", cfacts, dimsToQuery); // pick denorm tables for the picked fact and dimensions Set<Dimension> denormTables = new HashSet<Dimension>(); if (cfacts != null) { for (CandidateFact cfact : cfacts) { Set<Dimension> factDenormTables = deNormCtx.rewriteDenormctx(cfact, dimsToQuery, cfacts.size() > 1); denormTables.addAll(factDenormTables); if (cfacts.size() > 1) { factDimMap.get(cfact).addAll(factDenormTables); } } } else { denormTables.addAll(deNormCtx.rewriteDenormctx(null, dimsToQuery, false)); } dimsToQuery.putAll(pickCandidateDimsToQuery(denormTables)); log.info("facts:{}, dimsToQuery: {}", cfacts, dimsToQuery); // Prune join paths once denorm tables are picked if (autoJoinCtx != null) { // prune join paths for picked fact and dimensions autoJoinCtx.pruneAllPaths(cube, cfacts, dimsToQuery); } if (autoJoinCtx != null) { // add optional dims from Join resolver Set<Dimension> joiningTables = new HashSet<Dimension>(); if (cfacts != null && cfacts.size() > 1) { for (CandidateFact cfact : cfacts) { Set<Dimension> factJoiningTables = autoJoinCtx.pickOptionalTables(cfact, factDimMap.get(cfact), this); factDimMap.get(cfact).addAll(factJoiningTables); joiningTables.addAll(factJoiningTables); } } else { joiningTables.addAll(autoJoinCtx.pickOptionalTables(null, dimsToQuery.keySet(), this)); } dimsToQuery.putAll(pickCandidateDimsToQuery(joiningTables)); } log.info("Picked Fact:{} dimsToQuery: {}", cfacts, dimsToQuery); pickedDimTables = dimsToQuery.values(); pickedFacts = cfacts; if (cfacts != null) { if (cfacts.size() > 1) { // Update ASTs for each fact for (CandidateFact cfact : cfacts) { cfact.updateASTs(this); } whereAST = MultiFactHQLContext.convertHavingToWhere( havingAST, this, cfacts, new DefaultAliasDecider()); } } hqlContext = createHQLContext(cfacts, dimsToQuery, factDimMap); return hqlContext.toHQL(); }