Skip to content
Open
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 @@ -659,6 +659,14 @@
this.visit(jsonTableFunction, null);
}

default <S> T visit(XmlTableFunction xmlTableFunction, S context) {
return visit((Function) xmlTableFunction, context);
}

default void visit(XmlTableFunction xmlTableFunction) {
this.visit(xmlTableFunction, null);
}

<S> T visit(ConnectByRootOperator connectByRootOperator, S context);

default void visit(ConnectByRootOperator connectByRootOperator) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -758,14 +758,19 @@
return visitExpressions(jsonTableFunction, context, jsonTableFunction.getAllExpressions());
}

@Override
public <S> T visit(XmlTableFunction xmlTableFunction, S context) {
return visitExpressions(xmlTableFunction, context, xmlTableFunction.getAllExpressions());
}

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

Check warning on line 768 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 768 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 773 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 773 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 @@ -793,7 +798,7 @@
if (selectVisitor != null) {
if (select.getWithItemsList() != null) {
for (WithItem<?> item : select.getWithItemsList()) {
item.accept(selectVisitor, context);

Check warning on line 801 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 801 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
231 changes: 231 additions & 0 deletions src/main/java/net/sf/jsqlparser/expression/XmlTableFunction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/*-
* #%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.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.create.table.ColDataType;

/**
* Represents an {@code XMLTABLE} table function (SQL/XML standard, supported by PostgreSQL and
* Oracle), which turns an XML document into a relational row set, e.g.:
*
* <pre>
* XMLTABLE('//ROWS/ROW'
* PASSING data
* COLUMNS id int PATH '@id',
* ordinality FOR ORDINALITY,
* country_id text PATH 'COUNTRY_ID',
* size float PATH 'SIZE' DEFAULT 0)
* </pre>
*
* It is the XML counterpart of {@link JsonTableFunction} and mirrors its structure, without the
* JSON-specific wrapper/error/plan clauses.
*/
public class XmlTableFunction extends Function {

private Expression rowPathExpression;
private final List<XmlTablePassingClause> passingClauses = new ArrayList<>();
private final List<XmlTableColumnDefinition> columnDefinitions = new ArrayList<>();

public static class XmlTablePassingClause extends ASTNodeAccessImpl implements Serializable {
private Expression valueExpression;
private String name;

public Expression getValueExpression() {
return valueExpression;
}

public XmlTablePassingClause setValueExpression(Expression valueExpression) {
this.valueExpression = valueExpression;
return this;
}

public String getName() {
return name;
}

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

public void collectExpressions(List<Expression> expressions) {
if (valueExpression != null) {
expressions.add(valueExpression);
}
}

@Override
public String toString() {
return valueExpression + (name != null ? " AS " + name : "");
}
}

public static class XmlTableColumnDefinition extends ASTNodeAccessImpl implements Serializable {
private String columnName;
private boolean forOrdinality;
private ColDataType dataType;
private Expression pathExpression;
private Expression defaultExpression;

public String getColumnName() {
return columnName;
}

public XmlTableColumnDefinition setColumnName(String columnName) {
this.columnName = columnName;
return this;
}

public boolean isForOrdinality() {
return forOrdinality;
}

public XmlTableColumnDefinition setForOrdinality(boolean forOrdinality) {
this.forOrdinality = forOrdinality;
return this;
}

public ColDataType getDataType() {
return dataType;
}

public XmlTableColumnDefinition setDataType(ColDataType dataType) {
this.dataType = dataType;
return this;
}

public Expression getPathExpression() {
return pathExpression;
}

public XmlTableColumnDefinition setPathExpression(Expression pathExpression) {
this.pathExpression = pathExpression;
return this;
}

public Expression getDefaultExpression() {
return defaultExpression;
}

public XmlTableColumnDefinition setDefaultExpression(Expression defaultExpression) {
this.defaultExpression = defaultExpression;
return this;
}

public void collectExpressions(List<Expression> expressions) {
if (pathExpression != null) {
expressions.add(pathExpression);
}
if (defaultExpression != null) {
expressions.add(defaultExpression);
}
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder(columnName);
if (forOrdinality) {
builder.append(" FOR ORDINALITY");
return builder.toString();
}
if (dataType != null) {
builder.append(" ").append(dataType);
}
if (pathExpression != null) {
builder.append(" PATH ").append(pathExpression);
}
if (defaultExpression != null) {
builder.append(" DEFAULT ").append(defaultExpression);
}
return builder.toString();
}
}

public Expression getRowPathExpression() {
return rowPathExpression;
}

public XmlTableFunction setRowPathExpression(Expression rowPathExpression) {
this.rowPathExpression = rowPathExpression;
return this;
}

public List<XmlTablePassingClause> getPassingClauses() {
return passingClauses;
}

public XmlTableFunction addPassingClause(XmlTablePassingClause passingClause) {
passingClauses.add(passingClause);
return this;
}

public List<XmlTableColumnDefinition> getColumnDefinitions() {
return columnDefinitions;
}

public XmlTableFunction addColumnDefinition(XmlTableColumnDefinition columnDefinition) {
columnDefinitions.add(columnDefinition);
return this;
}

public List<Expression> getAllExpressions() {
List<Expression> expressions = new ArrayList<>();
if (rowPathExpression != null) {
expressions.add(rowPathExpression);
}
for (XmlTablePassingClause passingClause : passingClauses) {
passingClause.collectExpressions(expressions);
}
for (XmlTableColumnDefinition columnDefinition : columnDefinitions) {
columnDefinition.collectExpressions(expressions);
}
return expressions;
}

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

@Override
public String toString() {
StringBuilder builder = new StringBuilder("XMLTABLE(");
builder.append(rowPathExpression);
if (!passingClauses.isEmpty()) {
builder.append(" PASSING ");
boolean first = true;
for (XmlTablePassingClause passingClause : passingClauses) {
if (!first) {
builder.append(", ");
}
builder.append(passingClause);
first = false;
}
}
if (!columnDefinitions.isEmpty()) {
builder.append(" COLUMNS ");
boolean first = true;
for (XmlTableColumnDefinition columnDefinition : columnDefinitions) {
if (!first) {
builder.append(", ");
}
builder.append(columnDefinition);
first = false;
}
}
builder.append(")");
return builder.toString();
}
}
19 changes: 16 additions & 3 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -768,17 +768,20 @@ public <S> Void visit(AnalyticExpression analytic, S context) {
if (analytic.getWindowElement() != null) {
if (analytic.getWindowElement().getRange() != null) {
if (analytic.getWindowElement().getRange().getStart() != null
&& analytic.getWindowElement().getRange().getStart().getExpression() != null) {
&& analytic.getWindowElement().getRange().getStart()
.getExpression() != null) {
analytic.getWindowElement().getRange().getStart().getExpression().accept(this,
context);
}
if (analytic.getWindowElement().getRange().getEnd() != null
&& analytic.getWindowElement().getRange().getEnd().getExpression() != null) {
&& analytic.getWindowElement().getRange().getEnd()
.getExpression() != null) {
analytic.getWindowElement().getRange().getEnd().getExpression().accept(this,
context);
}
}
if (analytic.getWindowElement().getOffset() != null && analytic.getWindowElement().getOffset().getExpression() != null) {
if (analytic.getWindowElement().getOffset() != null
&& analytic.getWindowElement().getOffset().getExpression() != null) {
analytic.getWindowElement().getOffset().getExpression().accept(this, context);
}

Expand Down Expand Up @@ -1792,6 +1795,16 @@ public <S> Void visit(JsonTableFunction expression, S context) {
return null;
}

@Override
public <S> Void visit(XmlTableFunction expression, S context) {
for (Expression xmlExpression : expression.getAllExpressions()) {
if (xmlExpression != null) {
xmlExpression.accept(this, context);
}
}
return null;
}

@Override
public <S> Void visit(ConnectByRootOperator connectByRootOperator, S context) {
connectByRootOperator.getColumn().accept(this, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import net.sf.jsqlparser.expression.JsonExpression;
import net.sf.jsqlparser.expression.JsonFunction;
import net.sf.jsqlparser.expression.JsonTableFunction;
import net.sf.jsqlparser.expression.XmlTableFunction;
import net.sf.jsqlparser.expression.KeepExpression;
import net.sf.jsqlparser.expression.KeyExpression;
import net.sf.jsqlparser.expression.LambdaExpression;
Expand Down Expand Up @@ -1659,6 +1660,12 @@ public <S> StringBuilder visit(JsonTableFunction expression, S context) {
return builder;
}

@Override
public <S> StringBuilder visit(XmlTableFunction expression, S context) {
builder.append(expression);
return builder;
}

@Override
public <S> StringBuilder visit(ConnectByRootOperator connectByRootOperator, S context) {
builder.append("CONNECT_BY_ROOT ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import net.sf.jsqlparser.expression.JsonExpression;
import net.sf.jsqlparser.expression.JsonFunction;
import net.sf.jsqlparser.expression.JsonTableFunction;
import net.sf.jsqlparser.expression.XmlTableFunction;
import net.sf.jsqlparser.expression.KeepExpression;
import net.sf.jsqlparser.expression.KeyExpression;
import net.sf.jsqlparser.expression.LambdaExpression;
Expand Down Expand Up @@ -1051,6 +1052,14 @@ public <S> Void visit(JsonTableFunction expression, S context) {
return null;
}

@Override
public <S> Void visit(XmlTableFunction expression, S context) {
for (Expression xmlExpression : expression.getAllExpressions()) {
validateOptionalExpression(xmlExpression, this);
}
return null;
}

@Override
public <S> Void visit(ConnectByRootOperator connectByRootOperator, S context) {
connectByRootOperator.getColumn().accept(this, context);
Expand Down
Loading
Loading