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 @@ -95,7 +95,7 @@
}

default <S> T visitLimit(Limit limit, S context) {
if (limit != null && !limit.isLimitNull() && !limit.isLimitAll()) {

Check warning on line 98 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java

View workflow job for this annotation

GitHub Actions / Maven Verify (macos-latest)

[deprecation] isLimitAll() in Limit has been deprecated

Check warning on line 98 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java

View workflow job for this annotation

GitHub Actions / Maven Verify (macos-latest)

[deprecation] isLimitNull() in Limit has been deprecated

Check warning on line 98 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java

View workflow job for this annotation

GitHub Actions / Maven Verify (ubuntu-latest)

[deprecation] isLimitAll() in Limit has been deprecated

Check warning on line 98 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java

View workflow job for this annotation

GitHub Actions / Maven Verify (ubuntu-latest)

[deprecation] isLimitNull() in Limit has been deprecated
if (limit.getOffset() != null) {
limit.getOffset().accept(this, context);
}
Expand Down Expand Up @@ -621,6 +621,14 @@
this.visit(arrayConstructor, null);
}

default <S> T visit(MapExpression mapExpression, S context) {
return null;
}

default void visit(MapExpression mapExpression) {
this.visit(mapExpression, null);
}

<S> T visit(VariableAssignment variableAssignment, S context);

default void visit(VariableAssignment variableAssignment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
Expand Down Expand Up @@ -693,6 +694,16 @@
return visitExpressions(arrayConstructor, context, arrayConstructor.getExpressions());
}

@Override
public <S> T visit(MapExpression mapExpression, S context) {
ArrayList<Expression> subExpressions = new ArrayList<>();
for (Map.Entry<Expression, Expression> entry : mapExpression.getEntries()) {
subExpressions.add(entry.getKey());
subExpressions.add(entry.getValue());
}
return visitExpressions(mapExpression, context, subExpressions);
}

@Override
public <S> T visit(VariableAssignment variableAssignment, S context) {
return visitExpressions(variableAssignment, context, variableAssignment.getVariable(),
Expand Down Expand Up @@ -765,12 +776,12 @@

@Override
public <S> T visit(ConnectByRootOperator connectByRootOperator, S context) {
return connectByRootOperator.getColumn().accept(this, context);

Check warning on line 779 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

View workflow job for this annotation

GitHub Actions / Maven Verify (macos-latest)

[deprecation] getColumn() in ConnectByRootOperator has been deprecated

Check warning on line 779 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

View workflow job for this annotation

GitHub Actions / Maven Verify (ubuntu-latest)

[deprecation] getColumn() in ConnectByRootOperator has been deprecated
}

@Override
public <S> T visit(ConnectByPriorOperator connectByPriorOperator, S context) {
return connectByPriorOperator.getColumn().accept(this, context);

Check warning on line 784 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

View workflow job for this annotation

GitHub Actions / Maven Verify (macos-latest)

[deprecation] getColumn() in ConnectByPriorOperator has been deprecated

Check warning on line 784 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

View workflow job for this annotation

GitHub Actions / Maven Verify (ubuntu-latest)

[deprecation] getColumn() in ConnectByPriorOperator has been deprecated
}

@Override
Expand Down Expand Up @@ -798,7 +809,7 @@
if (selectVisitor != null) {
if (select.getWithItemsList() != null) {
for (WithItem<?> item : select.getWithItemsList()) {
item.accept(selectVisitor, context);

Check warning on line 812 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

View workflow job for this annotation

GitHub Actions / Maven Verify (macos-latest)

[deprecation] <T,S>accept(SelectVisitor<T>,S) in WithItem has been deprecated

Check warning on line 812 in src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

View workflow job for this annotation

GitHub Actions / Maven Verify (ubuntu-latest)

[deprecation] <T,S>accept(SelectVisitor<T>,S) in WithItem has been deprecated
}
}
select.accept(selectVisitor, context);
Expand Down
79 changes: 79 additions & 0 deletions src/main/java/net/sf/jsqlparser/expression/MapExpression.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.expression;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/**
* DuckDB's {@code MAP {key: value, ...}} literal expression.
*
* @see <a href="https://duckdb.org/docs/sql/data_types/map.html">DuckDB MAP type</a>
*/
public class MapExpression extends ASTNodeAccessImpl implements Expression {

private List<Map.Entry<Expression, Expression>> entries = new ArrayList<>();

public MapExpression() {}

public MapExpression(Collection<? extends Map.Entry<Expression, Expression>> entries) {
this.entries.addAll(entries);
}

public List<Map.Entry<Expression, Expression>> getEntries() {
return entries;
}

public void setEntries(List<Map.Entry<Expression, Expression>> entries) {
this.entries = entries;
}

public MapExpression withEntries(List<Map.Entry<Expression, Expression>> entries) {
setEntries(entries);
return this;
}

public MapExpression addEntries(
Collection<? extends Map.Entry<Expression, Expression>> entries) {
this.entries.addAll(entries);
return this;
}

public MapExpression addEntry(Expression key, Expression value) {
entries.add(new AbstractMap.SimpleEntry<>(key, value));
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("MAP {");
for (int i = 0; i < entries.size(); i++) {
if (i > 0) {
builder.append(", ");
}
Map.Entry<Expression, Expression> entry = entries.get(i);
builder.append(entry.getKey()).append(": ").append(entry.getValue());
}
return builder.append("}");
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}

@Override
public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
return expressionVisitor.visit(this, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
*/
package net.sf.jsqlparser.statement.select;

import java.util.Collection;
import java.util.List;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.imprt.Import;
import net.sf.jsqlparser.statement.piped.FromQuery;

import java.util.Collection;
import java.util.List;

public interface FromItemVisitor<T> {

default <S> T visitFromItem(FromItem fromItem, S context) {
Expand Down Expand Up @@ -85,6 +84,14 @@ default void visit(PlainSelect plainSelect) {
this.visit(plainSelect, null);
}

default <S> T visit(PivotQuery pivotQuery, S context) {
return null;
}

default void visit(PivotQuery pivotQuery) {
this.visit(pivotQuery, null);
}

<S> T visit(SetOperationList setOperationList, S context);

default void visit(SetOperationList setOperationList) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package net.sf.jsqlparser.statement.select;

import java.util.ArrayList;
import java.util.Collection;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
Expand All @@ -17,9 +19,6 @@
import net.sf.jsqlparser.statement.imprt.Import;
import net.sf.jsqlparser.statement.piped.FromQuery;

import java.util.ArrayList;
import java.util.Collection;

@SuppressWarnings({"PMD.UncommentedEmptyMethodBody"})
public class FromItemVisitorAdapter<T> implements FromItemVisitor<T> {
private SelectVisitor<T> selectVisitor;
Expand Down Expand Up @@ -125,6 +124,11 @@ public <S> T visit(PlainSelect plainSelect, S context) {
return plainSelect.accept(selectVisitor, context);
}

@Override
public <S> T visit(PivotQuery pivotQuery, S context) {
return pivotQuery.accept(selectVisitor, context);
}

@Override
public <S> T visit(SetOperationList setOperationList, S context) {
ArrayList<T> results = new ArrayList<>();
Expand Down
160 changes: 160 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/select/PivotQuery.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement.select;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;

/**
* DuckDB's simplified {@code PIVOT} query.
*
* <p>
* Unlike {@link Pivot}, which is a clause attached to a {@link FromItem}, this construct is a query
* in its own right and can therefore be used as a statement, CTE, or parenthesized subquery.
*
* @see <a href="https://duckdb.org/docs/sql/statements/pivot.html">DuckDB PIVOT</a>
*/
public class PivotQuery extends Select {

private FromItem fromItem;
private ExpressionList<Expression> onExpressions;
private List<SelectItem<Function>> usingItems;
private ExpressionList<Expression> groupByExpressions;

public FromItem getFromItem() {
return fromItem;
}

public void setFromItem(FromItem fromItem) {
this.fromItem = fromItem;
}

public PivotQuery withFromItem(FromItem fromItem) {
setFromItem(fromItem);
return this;
}

public ExpressionList<Expression> getOnExpressions() {
return onExpressions;
}

public void setOnExpressions(ExpressionList<Expression> onExpressions) {
this.onExpressions = onExpressions;
}

public PivotQuery withOnExpressions(ExpressionList<Expression> onExpressions) {
setOnExpressions(onExpressions);
return this;
}

public PivotQuery addOnExpressions(Expression... expressions) {
return addOnExpressions(Arrays.asList(expressions));
}

public PivotQuery addOnExpressions(Collection<? extends Expression> expressions) {
ExpressionList<Expression> collection =
Optional.ofNullable(getOnExpressions()).orElseGet(ExpressionList::new);
collection.addAll(expressions);
return withOnExpressions(collection);
}

public List<SelectItem<Function>> getUsingItems() {
return usingItems;
}

public void setUsingItems(List<SelectItem<Function>> usingItems) {
this.usingItems = usingItems;
}

public PivotQuery withUsingItems(List<SelectItem<Function>> usingItems) {
setUsingItems(usingItems);
return this;
}

public PivotQuery addUsingItems(SelectItem<Function>... usingItems) {
List<SelectItem<Function>> collection =
Optional.ofNullable(getUsingItems()).orElseGet(ArrayList::new);
Collections.addAll(collection, usingItems);
return withUsingItems(collection);
}

public PivotQuery addUsingItems(Collection<? extends SelectItem<Function>> usingItems) {
List<SelectItem<Function>> collection =
Optional.ofNullable(getUsingItems()).orElseGet(ArrayList::new);
collection.addAll(usingItems);
return withUsingItems(collection);
}

public ExpressionList<Expression> getGroupByExpressions() {
return groupByExpressions;
}

public void setGroupByExpressions(ExpressionList<Expression> groupByExpressions) {
this.groupByExpressions = groupByExpressions;
}

public PivotQuery withGroupByExpressions(ExpressionList<Expression> groupByExpressions) {
setGroupByExpressions(groupByExpressions);
return this;
}

public PivotQuery addGroupByExpressions(Expression... expressions) {
return addGroupByExpressions(Arrays.asList(expressions));
}

public PivotQuery addGroupByExpressions(Collection<? extends Expression> expressions) {
ExpressionList<Expression> collection =
Optional.ofNullable(getGroupByExpressions()).orElseGet(ExpressionList::new);
collection.addAll(expressions);
return withGroupByExpressions(collection);
}

@Override
public StringBuilder appendSelectBodyTo(StringBuilder builder) {
builder.append("PIVOT ").append(fromItem);
if (onExpressions != null) {
builder.append(" ON ").append(onExpressions);
}
if (usingItems != null) {
builder.append(" USING ").append(Select.getStringList(usingItems));
}
if (groupByExpressions != null) {
builder.append(" GROUP BY ").append(groupByExpressions);
}
return builder;
}

@Override
public <T, S> T accept(SelectVisitor<T> selectVisitor, S context) {
return selectVisitor.visit(this, context);
}

@Override
public <T, S> T accept(FromItemVisitor<T> fromItemVisitor, S context) {
return fromItemVisitor.visit(this, context);
}

@Override
public SampleClause getSampleClause() {
return null;
}

@Override
public FromItem setSampleClause(SampleClause sampleClause) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@
*/
package net.sf.jsqlparser.statement.select;

import java.util.List;
import net.sf.jsqlparser.statement.OutputClause;
import net.sf.jsqlparser.statement.piped.FromQuery;

import java.util.List;

public interface SelectVisitor<T> {
default <S> T visitWithItems(List<WithItem<?>> withItemsList, S context) {
if (withItemsList != null) {
for (WithItem<?> withItem : withItemsList) {
withItem.accept(this, context);

Check warning on line 20 in src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java

View workflow job for this annotation

GitHub Actions / Maven Verify (macos-latest)

[deprecation] <T,S>accept(SelectVisitor<T>,S) in WithItem has been deprecated

Check warning on line 20 in src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java

View workflow job for this annotation

GitHub Actions / Maven Verify (ubuntu-latest)

[deprecation] <T,S>accept(SelectVisitor<T>,S) in WithItem has been deprecated
}
}
return null;
Expand All @@ -40,6 +39,14 @@
this.visit(plainSelect, null);
}

default <S> T visit(PivotQuery pivotQuery, S context) {
return null;
}

default void visit(PivotQuery pivotQuery) {
this.visit(pivotQuery, null);
}

<S> T visit(FromQuery fromQuery, S context);

<S> T visit(SetOperationList setOpList, S context);
Expand Down
Loading
Loading