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
40 changes: 40 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 @@ -23,7 +23,11 @@
import net.sf.jsqlparser.statement.DescribeStatement;
import net.sf.jsqlparser.statement.ExplainStatement;
import net.sf.jsqlparser.statement.ResetStatement;
import net.sf.jsqlparser.statement.RollbackStatement;
import net.sf.jsqlparser.statement.SavepointStatement;
import net.sf.jsqlparser.statement.SetConstraintsStatement;
import net.sf.jsqlparser.statement.SetStatement;
import net.sf.jsqlparser.statement.SetTransactionStatement;
import net.sf.jsqlparser.statement.ShowColumnsStatement;
import net.sf.jsqlparser.statement.ShowStatement;
import net.sf.jsqlparser.statement.TableMaintenanceStatement;
Expand Down Expand Up @@ -664,6 +668,18 @@ public enum Feature {
* @see Commit
*/
commit,
/**
* SQL "ROLLBACK" statement is allowed
*
* @see RollbackStatement
*/
rollback,
/**
* SQL "SAVEPOINT" statement and "ROLLBACK TO [SAVEPOINT]" are allowed
*
* @see SavepointStatement
*/
savepoint,
/** START TRANSACTION and dialect-specific BEGIN transaction statements. */
startTransaction,
/** RELEASE [SAVEPOINT] statements. */
Expand All @@ -676,6 +692,30 @@ public enum Feature {
transactionDeferrable,
/** MySQL WITH CONSISTENT SNAPSHOT transaction characteristic. */
transactionConsistentSnapshot,
/** MySQL [NO] RELEASE after COMMIT or ROLLBACK. */
transactionRelease,
/** PostgreSQL END and ABORT, the alternative spellings of COMMIT and ROLLBACK. */
transactionEndAbort,
/**
* SET TRANSACTION characteristics
*
* @see SetTransactionStatement
*/
setTransaction,
/** MySQL SET GLOBAL TRANSACTION. */
setTransactionGlobal,
/** MySQL SET PERSIST TRANSACTION and SET PERSIST_ONLY TRANSACTION. */
setTransactionPersist,
/** PostgreSQL SET SESSION CHARACTERISTICS AS TRANSACTION. */
setTransactionSessionCharacteristics,
/** PostgreSQL SET TRANSACTION SNAPSHOT. */
setTransactionSnapshot,
/**
* SET CONSTRAINTS {ALL | names} {DEFERRED | IMMEDIATE}
*
* @see SetConstraintsStatement
*/
setConstraints,
/**
* SQL "COMMENT ON" statement is allowed
*
Expand Down
60 changes: 31 additions & 29 deletions src/main/java/net/sf/jsqlparser/statement/Commit.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,59 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import java.util.Objects;

public class Commit extends ASTNodeAccessImpl implements Statement {
private TransactionKeyword keyword;
private TransactionChain chain;

public TransactionKeyword getKeyword() {
return keyword;
/** COMMIT, or its PostgreSQL spelling END. */
public class Commit extends TransactionCompletionStatement {
/** The keyword that starts the statement; both commit the current transaction. */
public enum Command {
COMMIT, END
}

public void setKeyword(TransactionKeyword keyword) {
this.keyword = keyword;
private Command command = Command.COMMIT;

public Command getCommand() {
return command;
}

public Commit withKeyword(TransactionKeyword keyword) {
setKeyword(keyword);
return this;
public void setCommand(Command command) {
this.command = Objects.requireNonNull(command, "command");
}

public TransactionChain getChain() {
return chain;
public Commit withCommand(Command command) {
setCommand(command);
return this;
}

public void setChain(TransactionChain chain) {
this.chain = chain;
public Commit withKeyword(TransactionKeyword keyword) {
setKeyword(keyword);
return this;
}

public Commit withChain(TransactionChain chain) {
setChain(chain);
return this;
}

public Commit withRelease(TransactionRelease release) {
setRelease(release);
return this;
}

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
public boolean isPostgresSpelling() {
return command == Command.END;
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("COMMIT");
if (keyword != null) {
builder.append(' ').append(keyword);
}
if (chain != null) {
builder.append(' ').append(chain);
}
return builder;
@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
public StringBuilder appendTo(StringBuilder builder) {
builder.append(command);
appendKeyword(builder);
return appendCompletion(builder);
}
}
70 changes: 37 additions & 33 deletions src/main/java/net/sf/jsqlparser/statement/RollbackStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,53 +25,61 @@

package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import java.util.Objects;

/**
* ROLLBACK, or its PostgreSQL spelling ABORT.
*
* @author are
*/
public class RollbackStatement extends ASTNodeAccessImpl implements Statement {
private TransactionKeyword keyword;
private TransactionChain chain;
public class RollbackStatement extends TransactionCompletionStatement {
/** The keyword that starts the statement; ABORT has no savepoint or FORCE form. */
public enum Command {
ROLLBACK, ABORT
}

private Command command = Command.ROLLBACK;
private boolean usingSavepointKeyword = false;
private String savepointName = null;
private String forceDistributedTransactionIdentifier = null;

public TransactionKeyword getKeyword() {
return keyword;
public Command getCommand() {
return command;
}

public void setKeyword(TransactionKeyword keyword) {
this.keyword = keyword;
public void setCommand(Command command) {
this.command = Objects.requireNonNull(command, "command");
}

public RollbackStatement withKeyword(TransactionKeyword keyword) {
setKeyword(keyword);
public RollbackStatement withCommand(Command command) {
setCommand(command);
return this;
}

public TransactionChain getChain() {
return chain;
}

public void setChain(TransactionChain chain) {
this.chain = chain;
public RollbackStatement withKeyword(TransactionKeyword keyword) {
setKeyword(keyword);
return this;
}

public RollbackStatement withChain(TransactionChain chain) {
setChain(chain);
return this;
}

public RollbackStatement withRelease(TransactionRelease release) {
setRelease(release);
return this;
}

public boolean isUsingWorkKeyword() {
return keyword == TransactionKeyword.WORK;
return getKeyword() == TransactionKeyword.WORK;
}

public void setUsingWorkKeyword(boolean usingWorkKeyword) {
if (usingWorkKeyword) {
keyword = TransactionKeyword.WORK;
} else if (keyword == TransactionKeyword.WORK) {
keyword = null;
setKeyword(TransactionKeyword.WORK);
} else if (getKeyword() == TransactionKeyword.WORK) {
setKeyword(null);
}
}

Expand Down Expand Up @@ -121,27 +129,23 @@ public RollbackStatement withForceDistributedTransactionIdentifier(
return this;
}

@Override
public boolean isPostgresSpelling() {
return command == Command.ABORT;
}

@Override
public StringBuilder appendTo(StringBuilder builder) {
builder.append("ROLLBACK");
if (keyword != null) {
builder.append(' ').append(keyword);
}
builder.append(command);
appendKeyword(builder);
if (savepointName != null && !savepointName.trim().isEmpty()) {
builder.append(" TO ").append(usingSavepointKeyword ? "SAVEPOINT " : "")
.append(savepointName);
} else if (forceDistributedTransactionIdentifier != null
&& !forceDistributedTransactionIdentifier.trim().isEmpty()) {
builder.append(" FORCE ").append(forceDistributedTransactionIdentifier);
}
if (chain != null) {
builder.append(' ').append(chain);
}
return builder;
}

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

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*-
* #%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;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
import net.sf.jsqlparser.statement.create.table.ConstraintAttributes;

/**
* {@code SET CONSTRAINTS {ALL | name [, ...]} {DEFERRED | IMMEDIATE}}, which changes when the
* deferrable constraints of the current transaction are checked.
*/
public class SetConstraintsStatement extends ASTNodeAccessImpl implements Statement {
private final List<String> constraintNames = new ArrayList<>();
private ConstraintAttributes.Initially timing;

public SetConstraintsStatement() {
this(ConstraintAttributes.Initially.IMMEDIATE);
}

public SetConstraintsStatement(ConstraintAttributes.Initially timing) {
setTiming(timing);
}

/**
* Mutable list of the named constraints, each possibly schema-qualified and kept as written. An
* empty list means ALL.
*/
public List<String> getConstraintNames() {
return constraintNames;
}

public SetConstraintsStatement addConstraintName(String name) {
constraintNames.add(Objects.requireNonNull(name, "name"));
return this;
}

/** Whether the statement applies to all deferrable constraints. */
public boolean isAll() {
return constraintNames.isEmpty();
}

/** The check timing, shared with the INITIALLY clause of constraint definitions. */
public ConstraintAttributes.Initially getTiming() {
return timing;
}

public void setTiming(ConstraintAttributes.Initially timing) {
this.timing = Objects.requireNonNull(timing, "timing");
}

public SetConstraintsStatement withTiming(ConstraintAttributes.Initially timing) {
setTiming(timing);
return this;
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("SET CONSTRAINTS ");
if (isAll()) {
builder.append("ALL");
} else {
builder.append(String.join(", ", constraintNames));
}
return builder.append(' ').append(timing);
}

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

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