Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ public class ParserKeywordsUtils {
{"PRIOR", RESTRICTED_ALIAS},
{"PROCEDURE", RESTRICTED_ALIAS},
{"PUBLIC", RESTRICTED_ALIAS},
{"RETURNS", RESTRICTED_JSQLPARSER},
{"RETURNING", RESTRICTED_JSQLPARSER},
{"RIGHT", RESTRICTED_SQL2016},
{"SAMPLE", RESTRICTED_ALIAS},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2025 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement.select;

import net.sf.jsqlparser.expression.Expression;

import java.io.Serializable;
import java.util.List;

public class WithFunctionDeclaration implements Serializable {
private String functionName;
private List<WithFunctionParameter> parameters;
private String returnType;
private Expression returnExpression;

public WithFunctionDeclaration() {}

public WithFunctionDeclaration(String functionName, List<WithFunctionParameter> parameters,
String returnType, Expression returnExpression) {
this.functionName = functionName;
this.parameters = parameters;
this.returnType = returnType;
this.returnExpression = returnExpression;
}

public String getFunctionName() {
return functionName;
}

public void setFunctionName(String functionName) {
this.functionName = functionName;
}

public List<WithFunctionParameter> getParameters() {
return parameters;
}

public void setParameters(List<WithFunctionParameter> parameters) {
this.parameters = parameters;
}

public String getReturnType() {
return returnType;
}

public void setReturnType(String returnType) {
this.returnType = returnType;
}

public Expression getReturnExpression() {
return returnExpression;
}

public void setReturnExpression(Expression returnExpression) {
this.returnExpression = returnExpression;
}

public WithFunctionDeclaration withFunctionName(String functionName) {
this.setFunctionName(functionName);
return this;
}

public WithFunctionDeclaration withParameters(List<WithFunctionParameter> parameters) {
this.setParameters(parameters);
return this;
}

public WithFunctionDeclaration withReturnType(String returnType) {
this.setReturnType(returnType);
return this;
}

public WithFunctionDeclaration withReturnExpression(Expression returnExpression) {
this.setReturnExpression(returnExpression);
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
builder
.append("FUNCTION ")
.append(functionName)
.append("(");
for (int i = 0; parameters != null && i < parameters.size(); i++) {
if (i > 0) {
builder.append(", ");
}
parameters.get(i).appendTo(builder);
}
return builder
.append(") RETURNS ")
.append(returnType)
.append(" RETURN ")
.append(returnExpression);
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2025 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement.select;

import java.io.Serializable;

public class WithFunctionParameter implements Serializable {
private String name;
private String type; // e.g., INT

public WithFunctionParameter() {}

public WithFunctionParameter(String name, String type) {
this.name = name;
this.type = type;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public WithFunctionParameter withName(String name) {
this.name = name;
return this;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public WithFunctionParameter withType(String type) {
this.type = type;
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
return builder.append(name).append(" ").append(type);
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}
}
53 changes: 36 additions & 17 deletions src/main/java/net/sf/jsqlparser/statement/select/WithItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class WithItem<K extends ParenthesedStatement> implements Serializable {
private K statement;
private Alias alias;
private List<SelectItem<?>> withItemList;
private WithFunctionDeclaration withFunctionDeclaration;
private boolean recursive = false;
private boolean usingNot = false;
private boolean materialized = false;
Expand Down Expand Up @@ -121,28 +122,46 @@ public void setWithItemList(List<SelectItem<?>> withItemList) {
this.withItemList = withItemList;
}

public WithFunctionDeclaration getWithFunctionDeclaration() {
return withFunctionDeclaration;
}

public void setWithFunctionDeclaration(WithFunctionDeclaration withFunctionDeclaration) {
this.withFunctionDeclaration = withFunctionDeclaration;
}

public WithItem<K> withWithFunctionDeclaration(
WithFunctionDeclaration withFunctionDeclaration) {
this.setWithFunctionDeclaration(withFunctionDeclaration);
return this;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(recursive ? "RECURSIVE " : "");
if (alias != null) {
builder.append(alias.getName());
}
if (withItemList != null) {
builder.append("(");
int size = withItemList.size();
for (int i = 0; i < size; i++) {
builder.append(withItemList.get(i)).append(i < size - 1 ? "," : "");
if (withFunctionDeclaration != null) {
builder.append(withFunctionDeclaration);
} else {
builder.append(recursive ? "RECURSIVE " : "");
if (alias != null) {
builder.append(alias.getName());
}
builder.append(")");
}
builder.append(" AS ");
if (materialized) {
builder.append(usingNot
? "NOT MATERIALIZED "
: "MATERIALIZED ");
if (withItemList != null) {
builder.append("(");
int size = withItemList.size();
for (int i = 0; i < size; i++) {
builder.append(withItemList.get(i)).append(i < size - 1 ? "," : "");
}
builder.append(")");
}
builder.append(" AS ");
if (materialized) {
builder.append(usingNot
? "NOT MATERIALIZED "
: "MATERIALIZED ");
}
builder.append(statement);
}
builder.append(statement);
return builder.toString();
}

Expand Down
38 changes: 21 additions & 17 deletions src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -717,23 +717,27 @@ public <S> StringBuilder visit(SetOperationList list, S context) {

@Override
public <S> StringBuilder visit(WithItem<?> withItem, S context) {
if (withItem.isRecursive()) {
builder.append("RECURSIVE ");
}
builder.append(withItem.getAlias().getName());
if (withItem.getWithItemList() != null) {
builder.append(" ")
.append(PlainSelect.getStringList(withItem.getWithItemList(), true, true));
}
builder.append(" AS ");
if (withItem.isMaterialized()) {
builder.append(withItem.isUsingNot()
? "NOT MATERIALIZED "
: "MATERIALIZED ");
}
StatementDeParser statementDeParser =
new StatementDeParser((ExpressionDeParser) expressionVisitor, this, builder);
statementDeParser.deParse(withItem.getParenthesedStatement());
if (withItem.getWithFunctionDeclaration() == null) {
if (withItem.isRecursive()) {
builder.append("RECURSIVE ");
}
builder.append(withItem.getAlias().getName());
if (withItem.getWithItemList() != null) {
builder.append(" ")
.append(PlainSelect.getStringList(withItem.getWithItemList(), true, true));
}
builder.append(" AS ");
if (withItem.isMaterialized()) {
builder.append(withItem.isUsingNot()
? "NOT MATERIALIZED "
: "MATERIALIZED ");
}
StatementDeParser statementDeParser =
new StatementDeParser((ExpressionDeParser) expressionVisitor, this, builder);
statementDeParser.deParse(withItem.getParenthesedStatement());
} else {
builder.append(withItem.getWithFunctionDeclaration().toString());
}
return builder;
}

Expand Down
Loading
Loading