Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support recursive CTEs #4250

Merged
merged 2 commits into from Aug 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -106,6 +106,7 @@ public final class SystemSessionProperties
public static final String FILTER_AND_PROJECT_MIN_OUTPUT_PAGE_SIZE = "filter_and_project_min_output_page_size";
public static final String FILTER_AND_PROJECT_MIN_OUTPUT_PAGE_ROW_COUNT = "filter_and_project_min_output_page_row_count";
public static final String DISTRIBUTED_SORT = "distributed_sort";
public static final String MAX_RECURSION_DEPTH = "max_recursion_depth";
public static final String USE_MARK_DISTINCT = "use_mark_distinct";
public static final String PREFER_PARTIAL_AGGREGATION = "prefer_partial_aggregation";
public static final String OPTIMIZE_TOP_N_ROW_NUMBER = "optimize_top_n_row_number";
Expand Down Expand Up @@ -448,6 +449,15 @@ public SystemSessionProperties(
"Parallelize sort across multiple nodes",
featuresConfig.isDistributedSortEnabled(),
false),
new PropertyMetadata<>(
MAX_RECURSION_DEPTH,
"Maximum recursion depth for recursive common table expression",
INTEGER,
Integer.class,
featuresConfig.getMaxRecursionDepth(),
false,
value -> validateIntegerValue(value, MAX_RECURSION_DEPTH, 1, false),
object -> object),
booleanProperty(
USE_MARK_DISTINCT,
"Implement DISTINCT aggregations using MarkDistinct",
Expand Down Expand Up @@ -890,6 +900,11 @@ public static boolean isDistributedSortEnabled(Session session)
return session.getSystemProperty(DISTRIBUTED_SORT, Boolean.class);
}

public static int getMaxRecursionDepth(Session session)
{
return session.getSystemProperty(MAX_RECURSION_DEPTH, Integer.class);
}

public static int getMaxGroupingSets(Session session)
{
return session.getSystemProperty(MAX_GROUPING_SETS, Integer.class);
Expand Down
35 changes: 35 additions & 0 deletions presto-main/src/main/java/io/prestosql/sql/analyzer/Analysis.java
Expand Up @@ -102,6 +102,12 @@ public class Analysis

private final Map<NodeRef<Table>, Query> namedQueries = new LinkedHashMap<>();

// map expandable query to the node being the inner recursive reference
private final Map<NodeRef<Query>, Node> expandableNamedQueries = new LinkedHashMap<>();

// map inner recursive reference in the expandable query to the recursion base scope
private final Map<NodeRef<Node>, Scope> expandableBaseScopes = new LinkedHashMap<>();

// Synthetic scope when a query does not have a FROM clause
// We need to track this separately because there's no node we can attach it to.
private final Map<NodeRef<QuerySpecification>, Scope> implicitFromScopes = new LinkedHashMap<>();
Expand Down Expand Up @@ -614,6 +620,35 @@ public void registerNamedQuery(Table tableReference, Query query)
namedQueries.put(NodeRef.of(tableReference), query);
}

public void registerExpandableQuery(Query query, Node recursiveReference)
{
requireNonNull(query, "query is null");
requireNonNull(recursiveReference, "recursiveReference is null");

expandableNamedQueries.put(NodeRef.of(query), recursiveReference);
}

public boolean isExpandableQuery(Query query)
{
return expandableNamedQueries.containsKey(NodeRef.of(query));
}

public Node getRecursiveReference(Query query)
{
checkArgument(isExpandableQuery(query), "query is not registered as expandable");
return expandableNamedQueries.get(NodeRef.of(query));
}

public void setExpandableBaseScope(Node node, Scope scope)
{
expandableBaseScopes.put(NodeRef.of(node), scope);
}

public Optional<Scope> getExpandableBaseScope(Node node)
{
return Optional.ofNullable(expandableBaseScopes.get(NodeRef.of(node)));
}

public void registerTableForView(Table tableReference)
{
tablesForView.push(requireNonNull(tableReference, "table is null"));
Expand Down
Expand Up @@ -96,6 +96,7 @@ public class FeaturesConfig
private boolean pagesIndexEagerCompactionEnabled;
private boolean distributedSort = true;
private boolean omitDateTimeTypePrecision;
private int maxRecursionDepth = 10;

private boolean dictionaryAggregation;

Expand Down Expand Up @@ -1003,6 +1004,18 @@ public FeaturesConfig setDistributedSortEnabled(boolean enabled)
return this;
}

public int getMaxRecursionDepth()
{
return maxRecursionDepth;
}

@Config("max-recursion-depth")
public FeaturesConfig setMaxRecursionDepth(int maxRecursionDepth)
{
this.maxRecursionDepth = maxRecursionDepth;
return this;
}

public int getMaxGroupingSets()
{
return maxGroupingSets;
Expand Down
Expand Up @@ -73,6 +73,11 @@ private Scope(
this.namedQueries = ImmutableMap.copyOf(requireNonNull(namedQueries, "namedQueries is null"));
}

public Scope withRelationType(RelationType relationType)
{
return new Scope(parent, queryBoundary, relationId, relationType, namedQueries);
}

public Scope getQueryBoundaryScope()
{
Scope scope = this;
Expand Down