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 @@ -10,6 +10,7 @@
package net.sf.jsqlparser.expression;

import java.util.List;
import net.sf.jsqlparser.statement.execute.ExecuteArgument;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
Expand Down Expand Up @@ -72,6 +73,10 @@

public interface ExpressionVisitor<T> {

default <S> T visit(ExecuteArgument argument, S context) {
return argument.getExpression().accept(this, context);
}

default <S> T visitExpressions(ExpressionList<? extends Expression> expressions, S context) {
if (expressions != null) {
expressions.forEach(expression -> expression.accept(this, context));
Expand All @@ -96,7 +101,7 @@
}

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

Check warning on line 104 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 104 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

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

View workflow job for this annotation

GitHub Actions / Maven Verify (windows-latest)

[deprecation] isLimitAll() in Limit has been deprecated

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

View workflow job for this annotation

GitHub Actions / Maven Verify (windows-latest)

[deprecation] isLimitNull() in Limit has been deprecated

Check warning on line 104 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 104 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
if (limit.getOffset() != null) {
limit.getOffset().accept(this, context);
}
Expand Down
40 changes: 29 additions & 11 deletions src/main/java/net/sf/jsqlparser/statement/execute/Execute.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
package net.sf.jsqlparser.statement.execute;

import java.util.Locale;
import java.util.StringJoiner;
import java.util.function.Consumer;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.select.PlainSelect;

import java.util.List;

Expand All @@ -33,13 +35,11 @@ public void setName(String name) {
}

public void setName(List<String> names) {
StringJoiner qualifiedName = new StringJoiner(".");
for (String item : names) {
if (this.name != null) {
this.name = this.name + "." + item;
} else {
this.name = item;
}
qualifiedName.add(item == null ? "" : item);
}
this.name = qualifiedName.toString();
}

public ExpressionList getExprList() {
Expand Down Expand Up @@ -70,11 +70,29 @@ public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {

@Override
public String toString() {
return execType.name() + " " + name
+ (exprList != null
? " " + PlainSelect.getStringList(exprList, true,
exprList instanceof ParenthesedExpressionList)
: "");
StringBuilder builder = new StringBuilder();
return appendTo(builder, builder::append).toString();
}

public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionPrinter) {
builder.append(execType.name()).append(' ').append(name);
if (exprList != null) {
builder.append(' ');
boolean brackets = exprList instanceof ParenthesedExpressionList;
if (brackets) {
builder.append('(');
}
for (int i = 0; i < exprList.size(); i++) {
if (i > 0) {
builder.append(", ");
}
expressionPrinter.accept((Expression) exprList.get(i));
}
if (brackets) {
builder.append(')');
}
}
return builder;
}

public Execute withExecType(ExecType execType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*-
* #%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.execute;

import java.util.Objects;
import java.util.function.Consumer;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;

/** An EXEC argument with a call-specific OUTPUT modifier. */
public class ExecuteArgument extends ASTNodeAccessImpl implements Expression {
private Expression expression;
private boolean output;

public ExecuteArgument(Expression expression, boolean output) {
setExpression(expression);
this.output = output;
}

public Expression getExpression() {
return expression;
}

public void setExpression(Expression expression) {
this.expression = Objects.requireNonNull(expression, "expression");
}

public boolean isOutput() {
return output;
}

public void setOutput(boolean output) {
this.output = output;
}

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

public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionPrinter) {
expressionPrinter.accept(expression);
if (output) {
builder.append(" OUTPUT");
}
return builder;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
return appendTo(builder, builder::append).toString();
}
}
6 changes: 6 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
import net.sf.jsqlparser.statement.delete.ParenthesedDelete;
import net.sf.jsqlparser.statement.drop.Drop;
import net.sf.jsqlparser.statement.execute.Execute;
import net.sf.jsqlparser.statement.execute.ExecuteArgument;
import net.sf.jsqlparser.statement.export.Export;
import net.sf.jsqlparser.statement.grant.Grant;
import net.sf.jsqlparser.statement.imprt.Import;
Expand Down Expand Up @@ -1696,6 +1697,11 @@ public <S> Void visit(Execute execute, S context) {
return null;
}

@Override
public <S> Void visit(ExecuteArgument argument, S context) {
return argument.getExpression().accept(this, context);
}

@Override
public void visit(Execute execute) {
StatementVisitor.super.visit(execute);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
*/
package net.sf.jsqlparser.util.deparser;

import java.util.List;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.statement.execute.Execute;

Expand All @@ -27,24 +25,7 @@ public ExecuteDeParser(ExpressionVisitor<StringBuilder> expressionVisitor,

@Override
public void deParse(Execute execute) {
builder.append(execute.getExecType().name()).append(" ").append(execute.getName());
if (execute.isParenthesis()) {
builder.append(" (");
} else if (execute.getExprList() != null) {
builder.append(" ");
}
if (execute.getExprList() != null) {
List<Expression> expressions = execute.getExprList().getExpressions();
for (int i = 0; i < expressions.size(); i++) {
if (i > 0) {
builder.append(", ");
}
expressions.get(i).accept(expressionVisitor, null);
}
}
if (execute.isParenthesis()) {
builder.append(")");
}
execute.appendTo(builder, expression -> expression.accept(expressionVisitor, null));
}

public ExpressionVisitor<StringBuilder> getExpressionVisitor() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,12 @@ public <S> StringBuilder visit(UserVariable var, S context) {
return builder;
}

@Override
public <S> StringBuilder visit(
net.sf.jsqlparser.statement.execute.ExecuteArgument argument, S context) {
return argument.appendTo(builder, expression -> expression.accept(this, context));
}

@Override
public <S> StringBuilder visit(NumericBind bind, S context) {
builder.append(bind.toString());
Expand Down
56 changes: 46 additions & 10 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
// and must not be taken as the JSON path operator
private int mapKeyDepth = 0;

private Expression createOutputArgument(Expression argument) throws ParseException {
Expression value = argument;
if (argument instanceof VariableAssignment) {
value = ((VariableAssignment) argument).getExpression();
} else if (argument instanceof EqualsTo
&& ((EqualsTo) argument).getLeftExpression() instanceof UserVariable) {
value = ((EqualsTo) argument).getRightExpression();
}
if (!(value instanceof UserVariable || value instanceof JdbcParameter
|| value instanceof JdbcNamedParameter)) {
throw new ParseException("An OUTPUT argument must be a variable or bind parameter");
}
return new net.sf.jsqlparser.statement.execute.ExecuteArgument(argument, true);
}

private void linkAST(ASTNodeAccess access, Node node) {
access.setASTNode(node);
node.jjtSetValue(access);
Expand Down Expand Up @@ -10654,27 +10669,48 @@ EqualsTo VariableExpression(): {
}

Execute Execute(): {
Token token;
ObjectNames funcName;
ExpressionList expressionList = null;
ExpressionList expressionList;
Execute execute = new Execute();
List<Expression> namedExprList;
Expression expr;
}
{
(<K_EXEC> { execute.setExecType(Execute.ExecType.EXEC); }
| <K_EXECUTE> { execute.setExecType(Execute.ExecType.EXECUTE); }
| <K_CALL> { execute.setExecType(Execute.ExecType.CALL); } )

funcName=RelObjectNames() { execute.setName(funcName.getNames()); }
// A colon starts a bind argument here; it must not join the procedure name.
funcName=ColumnIdentifier() { execute.setName(funcName.getNames()); }
[ LOOKAHEAD(2) expressionList=ExecuteArguments() { execute.setExprList(expressionList); } ]
{ return execute; }
}

ExpressionList ExecuteArguments(): {
ExpressionList arguments = new ExpressionList();
Expression argument;
}
{
(
LOOKAHEAD(2) expressionList=ExpressionList() { execute.setExprList(expressionList); }
)?
LOOKAHEAD("(") arguments=ExpressionList()
|
argument=ExecuteArgument() { arguments.add(argument); }
( "," argument=ExecuteArgument() { arguments.add(argument); } )*
)
{ return arguments; }
}

Expression ExecuteArgument(): {
Expression argument;
boolean output = false;
}
{
argument=Expression()
[
LOOKAHEAD({ isAccessKeywordAhead("OUTPUT") || isAccessKeywordAhead("OUT") })
( <K_OUTPUT> | AccessKeyword("OUT") )
{ output = true; }
]
{ return output ? createOutputArgument(argument) : argument; }

{
return execute;
}
}

FullTextSearch FullTextSearch() : {
Expand Down
Loading
Loading