Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@

import org.apache.lens.cube.metadata.CubeFactTable;
import org.apache.lens.cube.parse.PruneCauses;
import org.apache.lens.cube.parse.StorageCandidate;
import org.apache.lens.server.api.error.LensException;


public class NoCandidateFactAvailableException extends LensException {

private final PruneCauses<CubeFactTable> briefAndDetailedError;
private final PruneCauses<StorageCandidate> briefAndDetailedError;

public NoCandidateFactAvailableException(PruneCauses<CubeFactTable> briefAndDetailedError) {
public NoCandidateFactAvailableException(PruneCauses<StorageCandidate> briefAndDetailedError) {
super(LensCubeErrorCode.NO_CANDIDATE_FACT_AVAILABLE.getLensErrorInfo(), briefAndDetailedError.getBriefCause());
this.briefAndDetailedError = briefAndDetailedError;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import lombok.Setter;

@EqualsAndHashCode
// TODO union : Change the class name To StoragePartition
public class FactPartition implements Comparable<FactPartition> {
@Getter
private final String partCol;
Expand All @@ -39,6 +40,8 @@ public class FactPartition implements Comparable<FactPartition> {
private final Set<String> storageTables = new LinkedHashSet<String>();
@Getter
private final UpdatePeriod period;

//TODO union : this is never set . Do we need this ?s
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used in lookahead.

@Getter
@Setter
private FactPartition containingPart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,24 @@ public void rewriteContext(CubeQueryContext cubeql) throws LensException {
|| hasMeasuresNotInDefaultAggregates(cubeql, cubeql.getHavingAST(), null, aggregateResolverDisabled)
|| hasMeasures(cubeql, cubeql.getWhereAST()) || hasMeasures(cubeql, cubeql.getGroupByAST())
|| hasMeasures(cubeql, cubeql.getOrderByAST())) {
Iterator<CandidateFact> factItr = cubeql.getCandidateFacts().iterator();
while (factItr.hasNext()) {
CandidateFact candidate = factItr.next();
if (candidate.fact.isAggregated()) {
cubeql.addFactPruningMsgs(candidate.fact,
CandidateTablePruneCause.missingDefaultAggregate());
factItr.remove();
//TODO union : Note : Pending : cube segmentation design may change the above assumption and Set<Candidate> can contain and mix of StorageCandidate and UnionSegmentCandidate. This step can then ignore UnionSegmentCandidate
Iterator<Candidate> candItr = cubeql.getCandidates().iterator();
while (candItr.hasNext()) {
Candidate candidate = candItr.next();
if (candidate instanceof StorageCandidate) {
StorageCandidate sc = (StorageCandidate) candidate;
if (sc.getFact().isAggregated()) {
cubeql.addStoragePruningMsg(sc, CandidateTablePruneCause.missingDefaultAggregate());
candItr.remove();
}
} else {
throw new LensException("Not a storage candidate!!");
}
}
nonDefaultAggregates = true;
log.info("Query has non default aggregates, no aggregate resolution will be done");
}

cubeql.pruneCandidateFactSet(CandidateTablePruneCode.MISSING_DEFAULT_AGGREGATE);

if (nonDefaultAggregates || aggregateResolverDisabled) {
return;
}
Expand Down
107 changes: 107 additions & 0 deletions lens-cube/src/main/java/org/apache/lens/cube/parse/Candidate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.apache.lens.cube.parse;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Set;

import org.apache.lens.cube.metadata.FactPartition;
import org.apache.lens.cube.metadata.TimeRange;
import org.apache.lens.server.api.error.LensException;

/**
* This interface represents candidates that are involved in different phases of query rewriting.
* At the lowest level, Candidate is represented by a StorageCandidate that has a fact on a storage
* and other joined dimensions (if any) that are required to answer the query or part of the query.
* At a higher level Candidate can also be a Join or a Union Candidate representing join or union
* between other candidates
*
* Different Re-writers will work on applicable candidates to produce a final candidate which will be used
* for generating the re-written query.
*/
public interface Candidate {

/**
* Returns all the fact columns
*
* @return
*/
Collection<String> getColumns();

/**
* Start Time for this candidate (calculated based on schema)
*
* @return
*/
Date getStartTime();

/**
* End Time for this candidate (calculated based on schema)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope this is exclusive? in line with our usage of half-open ranges everywhere.

*
* @return
*/
Date getEndTime();

/**
* Returns the cost of this candidate
*
* @return
*/
double getCost();

/**
* Returns true if this candidate contains the given candidate
*
* @param candidate
* @return
*/
boolean contains(Candidate candidate);

/**
* Returns child candidates of this candidate if any.
* Note: StorageCandidate will return null
*
* @return
*/
Collection<Candidate> getChildren();

/**
* Calculates if this candidate can answer the query for given time range based on actual data registered with
* the underlying candidate storages. This method will also update any internal candidate data structures that are
* required for writing the re-written query and to answer {@link #getParticipatingPartitions()}.
*
* @param timeRange : TimeRange to check completeness for. TimeRange consists of start time, end time and the
* partition column
* @param queriedTimeRange : User quried timerange
* @param failOnPartialData : fail fast if the candidate can answer the query only partially
* @return true if this Candidate can answer query for the given time range.
*/
boolean evaluateCompleteness(TimeRange timeRange, TimeRange queriedTimeRange, boolean failOnPartialData)
throws LensException;

/**
* Returns the set of fact partitions that will participate in this candidate.
* Note: This method can be called only after call to
* {@link #evaluateCompleteness(TimeRange, TimeRange, boolean)}
*
* @return
*/
Set<FactPartition> getParticipatingPartitions();

/**
* Checks whether an expression is evaluable by a candidate
* 1. For a JoinCandidate, atleast one of the child candidates should be able to answer the expression
* 2. For a UnionCandidate, all child candidates should answer the expression
*
* @param expr
* @return
*/
boolean isExpressionEvaluable(ExpressionResolver.ExpressionContext expr);

/**
* Gets the index positions of answerable measure phrases in CubeQueryContext#selectPhrases
* @return
*/
Set<Integer> getAnswerableMeasurePhraseIndices();

}
Loading