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
2 changes: 2 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/feature/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ public enum Feature {
*
* @see Execute
*/
oracleBlock,

execute, executeExec, executeCall, executeExecute,

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.statement.oracle.OracleBlock;
import net.sf.jsqlparser.statement.oracle.OracleAssignment;
import net.sf.jsqlparser.statement.oracle.OracleNullStatement;

import net.sf.jsqlparser.statement.role.CreateRole;
import net.sf.jsqlparser.statement.role.AlterRole;
import net.sf.jsqlparser.statement.grant.Revoke;
Expand Down Expand Up @@ -986,4 +990,24 @@ public <S> Void visit(AlterSubscription statement, S context) {
}
return null;
}

@Override
public <S> Void visit(OracleBlock block, S context) {
analysis.claimTopLevel();
return super.visit(block, context);
}

@Override
public <S> Void visit(OracleAssignment assignment, S context) {
analysis.claimTopLevel();
// Assignment to a local variable is not a database write.
return super.visit(assignment, context);
}

@Override
public <S> Void visit(OracleNullStatement statement, S context) {
analysis.claimTopLevel();
return null;
}

}
29 changes: 29 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.statement.oracle.OracleBlock;
import net.sf.jsqlparser.statement.oracle.OracleAssignment;
import net.sf.jsqlparser.statement.oracle.OracleNullStatement;

import net.sf.jsqlparser.statement.role.CreateRole;
import net.sf.jsqlparser.statement.role.AlterRole;
import net.sf.jsqlparser.statement.grant.Revoke;
Expand Down Expand Up @@ -520,4 +524,29 @@ default <S> T visit(AlterSubscription statement, S context) {
default void visit(AlterSubscription statement) {
visit(statement, null);
}

default <S> T visit(OracleBlock block, S context) {
return visit((Block) block, context);
}

default void visit(OracleBlock block) {
visit(block, null);
}

default <S> T visit(OracleAssignment assignment, S context) {
return null;
}

default void visit(OracleAssignment assignment) {
visit(assignment, null);
}

default <S> T visit(OracleNullStatement statement, S context) {
return null;
}

default void visit(OracleNullStatement statement) {
visit(statement, null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.statement.oracle.OracleBlock;
import net.sf.jsqlparser.statement.oracle.OracleAssignment;

import net.sf.jsqlparser.statement.role.CreateRole;
import net.sf.jsqlparser.statement.role.AlterRole;
import net.sf.jsqlparser.statement.role.RoleOption;
Expand Down Expand Up @@ -421,7 +424,7 @@ public <S> T visit(Statements statements, S context) {

@Override
public <S> T visit(Execute execute, S context) {

expressionVisitor.visitExpression(execute.getExprList(), context);
return null;
}

Expand Down Expand Up @@ -769,4 +772,19 @@ public <S> T visit(AlterSubscription statement, S context) {
});
return null;
}

@Override
public <S> T visit(OracleBlock block, S context) {
block.visitChildren(expression -> expression.accept(expressionVisitor, context),
statement -> statement.accept(this, context));
return null;
}

@Override
public <S> T visit(OracleAssignment assignment, S context) {
assignment.getTarget().accept(expressionVisitor, context);
assignment.getValue().accept(expressionVisitor, context);
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ public String toString() {
}

public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionPrinter) {
builder.append(execType.name()).append(' ').append(name);
if (execType != ExecType.IMPLICIT) {
builder.append(execType.name()).append(' ');
}
builder.append(name);
if (exprList != null) {
builder.append(' ');
boolean brackets = exprList instanceof ParenthesedExpressionList;
Expand Down Expand Up @@ -111,7 +114,7 @@ public Execute withExprList(ExpressionList exprList) {
}

public enum ExecType {
EXECUTE, EXEC, CALL;
EXECUTE, EXEC, CALL, IMPLICIT;

public static ExecType from(String type) {
return Enum.valueOf(ExecType.class, type.toUpperCase(Locale.ROOT));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*-
* #%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.oracle;

import java.util.function.Consumer;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;

/** Assignment to an Oracle block variable, record field or bind parameter. */
public class OracleAssignment implements Statement {
private Expression target;
private Expression value;

public OracleAssignment(Expression target, Expression value) {
this.target = target;
this.value = value;
}

public Expression getTarget() {
return target;
}

public void setTarget(Expression target) {
this.target = target;
}

public Expression getValue() {
return value;
}

public void setValue(Expression value) {
this.value = value;
}

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

public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> printer) {
printer.accept(target);
builder.append(" := ");
printer.accept(value);
return builder;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
return appendTo(builder, builder::append).toString();
}
}
191 changes: 191 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/oracle/OracleBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*-
* #%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.oracle;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.statement.Block;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.create.table.ColDataType;

/** An Oracle anonymous block with variable declarations and exception handlers. */
public class OracleBlock extends Block {
private final List<VariableDeclaration> declarations = new ArrayList<>();
private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();

public List<VariableDeclaration> getDeclarations() {
return declarations;
}

public List<ExceptionHandler> getExceptionHandlers() {
return exceptionHandlers;
}

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

public void visitChildren(Consumer<Expression> expressions, Consumer<Statement> statements) {
for (VariableDeclaration declaration : declarations) {
if (declaration.getInitializer() != null) {
expressions.accept(declaration.getInitializer());
}
}
if (getStatements() != null) {
getStatements().forEach(statements);
}
exceptionHandlers.forEach(handler -> handler.getStatements().forEach(statements));
}

public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressions,
Consumer<Statement> statements) {
if (!declarations.isEmpty()) {
builder.append("DECLARE\n");
declarations.forEach(declaration -> {
declaration.appendTo(builder, expressions);
builder.append(";\n");
});
}
builder.append("BEGIN\n");
appendStatements(builder, getStatements(), statements);
if (!exceptionHandlers.isEmpty()) {
builder.append("EXCEPTION\n");
for (ExceptionHandler handler : exceptionHandlers) {
builder.append("WHEN ").append(String.join(" OR ", handler.getExceptions()))
.append(" THEN\n");
appendStatements(builder, handler.getStatements(), statements);
}
}
builder.append("END");
if (hasSemicolonAfterEnd()) {
builder.append(';');
}
return builder;
}

private static void appendStatements(StringBuilder builder, Statements body,
Consumer<Statement> printer) {
if (body == null) {
return;
}
for (Statement statement : body) {
printer.accept(statement);
if (!(statement instanceof Block) || !((Block) statement).hasSemicolonAfterEnd()) {
builder.append(';');
}
builder.append('\n');
}
}

@Override
public StringBuilder appendTo(StringBuilder builder) {
return appendTo(builder, builder::append, builder::append);
}

public static class VariableDeclaration implements java.io.Serializable {
private String name;
private ColDataType dataType;
private boolean constant;
private boolean notNull;
private String initializerOperator = ":=";
private Expression initializer;

public String getName() {
return name;
}

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

public ColDataType getDataType() {
return dataType;
}

public void setDataType(ColDataType type) {
dataType = type;
}

public boolean isConstant() {
return constant;
}

public void setConstant(boolean value) {
constant = value;
}

public boolean isNotNull() {
return notNull;
}

public void setNotNull(boolean value) {
notNull = value;
}

public String getInitializerOperator() {
return initializerOperator;
}

public void setInitializerOperator(String operator) {
initializerOperator = operator;
}

public Expression getInitializer() {
return initializer;
}

public void setInitializer(Expression expression) {
initializer = expression;
}

public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> printer) {
builder.append(name).append(' ');
if (constant) {
builder.append("CONSTANT ");
}
builder.append(dataType);
if (notNull) {
builder.append(" NOT NULL");
}
if (initializer != null) {
builder.append(' ').append(initializerOperator).append(' ');
printer.accept(initializer);
}
return builder;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
return appendTo(builder, builder::append).toString();
}
}
public static class ExceptionHandler implements java.io.Serializable {
private final List<String> exceptions = new ArrayList<>();
private Statements statements;

public List<String> getExceptions() {
return exceptions;
}

public Statements getStatements() {
return statements;
}

public void setStatements(Statements statements) {
this.statements = statements;
}
}
}
Loading
Loading