Skip to content

Adds parsing and modeling of CTEs #1736

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

Merged
merged 5 commits into from
Feb 7, 2025
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions partiql-ast/api/partiql-ast.api
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ public final class org/partiql/ast/Ast {
public static final fun exprPosition (Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/expr/ExprPosition;
public static final fun exprQuerySet (Lorg/partiql/ast/QueryBody;)Lorg/partiql/ast/expr/ExprQuerySet;
public static final fun exprQuerySet (Lorg/partiql/ast/QueryBody;Lorg/partiql/ast/OrderBy;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/expr/ExprQuerySet;
public static final fun exprQuerySet (Lorg/partiql/ast/QueryBody;Lorg/partiql/ast/OrderBy;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/With;)Lorg/partiql/ast/expr/ExprQuerySet;
public static synthetic fun exprQuerySet$default (Lorg/partiql/ast/QueryBody;Lorg/partiql/ast/OrderBy;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;ILjava/lang/Object;)Lorg/partiql/ast/expr/ExprQuerySet;
public static synthetic fun exprQuerySet$default (Lorg/partiql/ast/QueryBody;Lorg/partiql/ast/OrderBy;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/With;ILjava/lang/Object;)Lorg/partiql/ast/expr/ExprQuerySet;
public static final fun exprRowValue (Ljava/util/List;)Lorg/partiql/ast/expr/ExprRowValue;
public static final fun exprRowValue (Ljava/util/List;Z)Lorg/partiql/ast/expr/ExprRowValue;
public static final fun exprSessionAttribute (Lorg/partiql/ast/expr/SessionAttribute;)Lorg/partiql/ast/expr/ExprSessionAttribute;
Expand Down Expand Up @@ -213,6 +215,8 @@ public final class org/partiql/ast/Ast {
public static final fun upsert (Lorg/partiql/ast/Identifier;Lorg/partiql/ast/Identifier$Simple;Lorg/partiql/ast/dml/InsertSource;)Lorg/partiql/ast/dml/Upsert;
public static final fun upsert (Lorg/partiql/ast/Identifier;Lorg/partiql/ast/dml/InsertSource;)Lorg/partiql/ast/dml/Upsert;
public static synthetic fun upsert$default (Lorg/partiql/ast/Identifier;Lorg/partiql/ast/Identifier$Simple;Lorg/partiql/ast/dml/InsertSource;ILjava/lang/Object;)Lorg/partiql/ast/dml/Upsert;
public static final fun with (Ljava/util/List;Z)Lorg/partiql/ast/With;
public static final fun withListElement (Lorg/partiql/ast/Identifier$Simple;Lorg/partiql/ast/expr/ExprQuerySet;Ljava/util/List;)Lorg/partiql/ast/WithListElement;
}

public abstract class org/partiql/ast/AstEnum : org/partiql/ast/AstNode {
Expand Down Expand Up @@ -431,6 +435,10 @@ public abstract class org/partiql/ast/AstRewriter : org/partiql/ast/AstVisitor {
public fun visitUpdateTargetStepField (Lorg/partiql/ast/dml/UpdateTargetStep$Field;Ljava/lang/Object;)Lorg/partiql/ast/AstNode;
public synthetic fun visitUpsert (Lorg/partiql/ast/dml/Upsert;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitUpsert (Lorg/partiql/ast/dml/Upsert;Ljava/lang/Object;)Lorg/partiql/ast/AstNode;
public synthetic fun visitWith (Lorg/partiql/ast/With;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitWith (Lorg/partiql/ast/With;Ljava/lang/Object;)Lorg/partiql/ast/AstNode;
public synthetic fun visitWithListElement (Lorg/partiql/ast/WithListElement;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitWithListElement (Lorg/partiql/ast/WithListElement;Ljava/lang/Object;)Lorg/partiql/ast/AstNode;
}

public abstract class org/partiql/ast/AstVisitor {
Expand Down Expand Up @@ -572,6 +580,8 @@ public abstract class org/partiql/ast/AstVisitor {
public fun visitUpdateTargetStepElement (Lorg/partiql/ast/dml/UpdateTargetStep$Element;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitUpdateTargetStepField (Lorg/partiql/ast/dml/UpdateTargetStep$Field;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitUpsert (Lorg/partiql/ast/dml/Upsert;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitWith (Lorg/partiql/ast/With;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitWithListElement (Lorg/partiql/ast/WithListElement;Ljava/lang/Object;)Ljava/lang/Object;
}

public final class org/partiql/ast/DataType : org/partiql/ast/AstEnum {
Expand Down Expand Up @@ -1054,21 +1064,27 @@ public class org/partiql/ast/Identifier$Simple$Builder {
public final class org/partiql/ast/JoinType : org/partiql/ast/AstEnum {
public static final field CROSS I
public static final field FULL I
public static final field FULL_CROSS I
public static final field FULL_OUTER I
public static final field INNER I
public static final field INNER_CROSS I
public static final field LEFT I
public static final field LEFT_CROSS I
public static final field LEFT_OUTER I
public static final field RIGHT I
public static final field RIGHT_CROSS I
public static final field RIGHT_OUTER I
public static fun CROSS ()Lorg/partiql/ast/JoinType;
public static fun FULL ()Lorg/partiql/ast/JoinType;
public static fun FULL_CROSS ()Lorg/partiql/ast/JoinType;
public static fun FULL_OUTER ()Lorg/partiql/ast/JoinType;
public static fun INNER ()Lorg/partiql/ast/JoinType;
public static fun INNER_CROSS ()Lorg/partiql/ast/JoinType;
public static fun LEFT ()Lorg/partiql/ast/JoinType;
public static fun LEFT_CROSS ()Lorg/partiql/ast/JoinType;
public static fun LEFT_OUTER ()Lorg/partiql/ast/JoinType;
public static fun RIGHT ()Lorg/partiql/ast/JoinType;
public static fun RIGHT_CROSS ()Lorg/partiql/ast/JoinType;
public static fun RIGHT_OUTER ()Lorg/partiql/ast/JoinType;
public fun accept (Lorg/partiql/ast/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object;
public fun code ()I
Expand Down Expand Up @@ -1455,6 +1471,46 @@ public abstract class org/partiql/ast/Statement : org/partiql/ast/AstNode {
public fun <init> ()V
}

public final class org/partiql/ast/With : org/partiql/ast/AstNode {
public fun <init> (Ljava/util/List;)V
public fun <init> (Ljava/util/List;Z)V
public fun accept (Lorg/partiql/ast/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object;
public static fun builder ()Lorg/partiql/ast/With$Builder;
public fun equals (Ljava/lang/Object;)Z
public fun getChildren ()Ljava/util/List;
public fun getElements ()Ljava/util/List;
public fun hashCode ()I
public fun isRecursive ()Z
}

public class org/partiql/ast/With$Builder {
public fun build ()Lorg/partiql/ast/With;
public fun elements (Ljava/util/List;)Lorg/partiql/ast/With$Builder;
public fun isRecursive (Z)Lorg/partiql/ast/With$Builder;
public fun toString ()Ljava/lang/String;
}

public final class org/partiql/ast/WithListElement : org/partiql/ast/AstNode {
public fun <init> (Lorg/partiql/ast/Identifier$Simple;Lorg/partiql/ast/expr/ExprQuerySet;)V
public fun <init> (Lorg/partiql/ast/Identifier$Simple;Lorg/partiql/ast/expr/ExprQuerySet;Ljava/util/List;)V
public fun accept (Lorg/partiql/ast/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object;
public static fun builder ()Lorg/partiql/ast/WithListElement$Builder;
public fun equals (Ljava/lang/Object;)Z
public fun getAsQuery ()Lorg/partiql/ast/expr/ExprQuerySet;
public fun getChildren ()Ljava/util/List;
public fun getColumnList ()Ljava/util/List;
public fun getQueryName ()Lorg/partiql/ast/Identifier$Simple;
public fun hashCode ()I
}

public class org/partiql/ast/WithListElement$Builder {
public fun asQuery (Lorg/partiql/ast/expr/ExprQuerySet;)Lorg/partiql/ast/WithListElement$Builder;
public fun build ()Lorg/partiql/ast/WithListElement;
public fun queryName (Lorg/partiql/ast/Identifier$Simple;)Lorg/partiql/ast/WithListElement$Builder;
public fun toString ()Ljava/lang/String;
public fun withColumnList (Ljava/util/List;)Lorg/partiql/ast/WithListElement$Builder;
}

public abstract class org/partiql/ast/ddl/AttributeConstraint : org/partiql/ast/AstNode {
protected final field name Lorg/partiql/ast/Identifier;
protected fun <init> (Lorg/partiql/ast/Identifier;)V
Expand Down Expand Up @@ -2422,6 +2478,7 @@ public class org/partiql/ast/expr/ExprPosition$Builder {

public final class org/partiql/ast/expr/ExprQuerySet : org/partiql/ast/expr/Expr {
public fun <init> (Lorg/partiql/ast/QueryBody;Lorg/partiql/ast/OrderBy;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;)V
public fun <init> (Lorg/partiql/ast/QueryBody;Lorg/partiql/ast/OrderBy;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/With;)V
public fun accept (Lorg/partiql/ast/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object;
public static fun builder ()Lorg/partiql/ast/expr/ExprQuerySet$Builder;
public fun equals (Ljava/lang/Object;)Z
Expand All @@ -2430,6 +2487,7 @@ public final class org/partiql/ast/expr/ExprQuerySet : org/partiql/ast/expr/Expr
public fun getLimit ()Lorg/partiql/ast/expr/Expr;
public fun getOffset ()Lorg/partiql/ast/expr/Expr;
public fun getOrderBy ()Lorg/partiql/ast/OrderBy;
public fun getWith ()Lorg/partiql/ast/With;
public fun hashCode ()I
}

Expand All @@ -2440,6 +2498,7 @@ public class org/partiql/ast/expr/ExprQuerySet$Builder {
public fun offset (Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/expr/ExprQuerySet$Builder;
public fun orderBy (Lorg/partiql/ast/OrderBy;)Lorg/partiql/ast/expr/ExprQuerySet$Builder;
public fun toString ()Ljava/lang/String;
public fun with (Lorg/partiql/ast/With;)Lorg/partiql/ast/expr/ExprQuerySet$Builder;
}

public final class org/partiql/ast/expr/ExprRowValue : org/partiql/ast/expr/Expr {
Expand Down
8 changes: 8 additions & 0 deletions partiql-ast/src/main/java/org/partiql/ast/AstVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,14 @@ public R visitLet(Let node, C ctx) {
return defaultVisit(node, ctx);
}

public R visitWith(With node, C ctx) {
return defaultVisit(node, ctx);
}

public R visitWithListElement(WithListElement node, C ctx) {
return defaultVisit(node, ctx);
}

public R visitLetBinding(Let.Binding node, C ctx) {
return defaultVisit(node, ctx);
}
Expand Down
31 changes: 31 additions & 0 deletions partiql-ast/src/main/java/org/partiql/ast/JoinType.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,27 @@ public final class JoinType extends AstEnum {
* Cross join variant.
*/
public static final int CROSS = 7;

/**
* Left cross join variant.
*/
public static final int LEFT_CROSS = 8;

/**
* Right cross join variant.
*/
public static final int RIGHT_CROSS = 9;

/**
* Outer cross join variant.
*/
public static final int INNER_CROSS = 10;

/**
* Full cross join variant.
*/
public static final int FULL_CROSS = 11;

public static JoinType INNER() {
return new JoinType(INNER);
}
Expand Down Expand Up @@ -84,6 +100,18 @@ public static JoinType LEFT_CROSS() {
return new JoinType(LEFT_CROSS);
}

public static JoinType RIGHT_CROSS() {
return new JoinType(RIGHT_CROSS);
}

public static JoinType INNER_CROSS() {
return new JoinType(INNER_CROSS);
}

public static JoinType FULL_CROSS() {
return new JoinType(FULL_CROSS);
}

private final int code;

private JoinType(int code) {
Expand All @@ -108,6 +136,9 @@ public String name() {
case FULL_OUTER: return "FULL_OUTER";
case CROSS: return "CROSS";
case LEFT_CROSS: return "LEFT_CROSS";
case RIGHT_CROSS: return "RIGHT_CROSS";
case INNER_CROSS: return "INNER_CROSS";
case FULL_CROSS: return "FULL_CROSS";
default: throw new IllegalStateException("Invalid JoinType code: " + code);
}
}
Expand Down
73 changes: 73 additions & 0 deletions partiql-ast/src/main/java/org/partiql/ast/With.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.partiql.ast;

import lombok.Builder;
import lombok.EqualsAndHashCode;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

/**
* <p>
* Represents a PartiQL WITH clause.
* </p>
* <p>{@code <with clause> ::= WITH [ RECURSIVE ] <with list>}</p>
* <p>{@code <with list> ::= <with list element> [ { <comma> <with list element> }... ]}</p>
* @see WithListElement
* @see org.partiql.ast.expr.ExprQuerySet
*/
@Builder(builderClassName = "Builder")
@EqualsAndHashCode(callSuper = false)
public final class With extends AstNode {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should there be a helper constructor for With in org.partiql.ast.Ast?


@NotNull
private final List<WithListElement> elements;

private final boolean isRecursive;

/**
* Creates a new WITH clause with the specified elements and RECURSIVE set to the specified value.
* @param elements the list of WITH list elements
* @param isRecursive true if this WITH clause specified RECURSIVE;
*/
public With(@NotNull List<WithListElement> elements, boolean isRecursive) {
this.elements = elements;
this.isRecursive = isRecursive;
}

/**
* Creates a new WITH clause with the specified elements and RECURSIVE set to false.
* @param elements the list of WITH list elements
*/
public With(@NotNull List<WithListElement> elements) {
this(elements, false);
}

@NotNull
@Override
public List<AstNode> getChildren() {
return new ArrayList<>(elements);
}

@Override
public <R, C> R accept(@NotNull AstVisitor<R, C> visitor, C ctx) {
return visitor.visitWith(this, ctx);
}

/**
* Returns the list of WITH list elements.
* @return the list of WITH list elements
*/
@NotNull
public List<WithListElement> getElements() {
return this.elements;
}

/**
* Returns whether this WITH clause specified RECURSIVE.
* @return whether this WITH clause specified RECURSIVE.
*/
public boolean isRecursive() {
return this.isRecursive;
}
}
109 changes: 109 additions & 0 deletions partiql-ast/src/main/java/org/partiql/ast/WithListElement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package org.partiql.ast;

import lombok.Builder;
import lombok.EqualsAndHashCode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.partiql.ast.expr.ExprQuerySet;

import java.util.ArrayList;
import java.util.List;

/**
* <p>
* Represents a {@code <with list element>}.
* </p>
* <p>
* {@code
* <with list element> ::=
* <query name>
* [ <left paren> <with column list> <right paren> ]
* AS <left paren> <query expression> <right paren>
* [ <search or cycle clause> ]
* }
* </p>
* <p>{@code <with column list> ::= <column name list>}</p>
* <p>{@code <column name list> ::= <column name> [ { <comma> <column name> }... ]}</p>
* <p>{@code <column name> ::= <identifier>}</p>
* @see With
* @see ExprQuerySet
*/
@Builder(builderClassName = "Builder")
@EqualsAndHashCode(callSuper = false)
public final class WithListElement extends AstNode {
// TODO: Add support for the search/cycle clause.

@NotNull
private final Identifier.Simple queryName;

@NotNull
private final ExprQuerySet asQuery;

@Nullable
private final List<Identifier.Simple> withColumnList;

/**
* Creates a new instance of {@link WithListElement}.
* @param queryName the name to bind
* @param asQuery the query that defines the with list element
* @param columnList the list of column names to be output from the query
*/
public WithListElement(@NotNull Identifier.Simple queryName, @NotNull ExprQuerySet asQuery, @Nullable List<Identifier.Simple> columnList) {
this.queryName = queryName;
this.asQuery = asQuery;
this.withColumnList = columnList;
}

/**
* Creates a new instance of {@link WithListElement}.
* @param queryName the name to bind
* @param asQuery the query that defines the with list element
*/
public WithListElement(@NotNull Identifier.Simple queryName, @NotNull ExprQuerySet asQuery) {
this(queryName, asQuery, null);
}

@NotNull
@Override
public List<AstNode> getChildren() {
List<AstNode> children = new ArrayList<>();
children.add(queryName);
if (withColumnList != null) {
children.addAll(withColumnList);
}
children.add(asQuery);
return children;
}

@Override
public <R, C> R accept(@NotNull AstVisitor<R, C> visitor, C ctx) {
return visitor.visitWithListElement(this, ctx);
}

/**
* Returns the query name.
* @return the query name
*/
@NotNull
public Identifier.Simple getQueryName() {
return this.queryName;
}

/**
* Returns the list of column names to be output from the query.
* @return the list of column names to be output from the query. This may return null.
*/
@Nullable
public List<Identifier.Simple> getColumnList() {
return this.withColumnList;
}

/**
* Returns the query that defines the with list element.
* @return the query that defines the with list element
*/
@NotNull
public ExprQuerySet getAsQuery() {
return this.asQuery;
}
}
Loading
Loading