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 @@ -16,12 +16,8 @@
import net.sf.jsqlparser.statement.create.fdw.ForeignDataWrapperFunctions;

public class AlterForeignDataWrapper extends ForeignDataStatement {
public enum Action {
OPTIONS, OWNER, RENAME
}

private String name;
private Action action = Action.OPTIONS;
private ForeignObjectAlterAction action = ForeignObjectAlterAction.OPTIONS;
private String newName;
private String owner;
private ForeignDataWrapperFunctions functions = new ForeignDataWrapperFunctions();
Expand All @@ -34,11 +30,11 @@ public void setName(String value) {
name = value;
}

public Action getAction() {
public ForeignObjectAlterAction getAction() {
return action;
}

public void setAction(Action value) {
public void setAction(ForeignObjectAlterAction value) {
action = value;
}

Expand Down Expand Up @@ -93,7 +89,7 @@ public StringBuilder appendTo(StringBuilder sql, Consumer<Expression> printer) {

@Override
public void visitExpressions(Consumer<Expression> visitor) {
if (action == Action.OPTIONS) {
if (action == ForeignObjectAlterAction.OPTIONS) {
super.visitExpressions(visitor);
}
}
Expand Down
12 changes: 4 additions & 8 deletions src/main/java/net/sf/jsqlparser/statement/alter/AlterServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
import net.sf.jsqlparser.statement.foreign.ForeignDataStatement;

public class AlterServer extends ForeignDataStatement {
public enum Action {
OPTIONS, OWNER, RENAME
}

private String name;
private Action action = Action.OPTIONS;
private ForeignObjectAlterAction action = ForeignObjectAlterAction.OPTIONS;
private String newName;
private String owner;
private Expression version;
Expand All @@ -33,11 +29,11 @@ public void setName(String value) {
name = value;
}

public Action getAction() {
public ForeignObjectAlterAction getAction() {
return action;
}

public void setAction(Action value) {
public void setAction(ForeignObjectAlterAction value) {
action = value;
}

Expand Down Expand Up @@ -95,7 +91,7 @@ public StringBuilder appendTo(StringBuilder sql, Consumer<Expression> printer) {

@Override
public void visitExpressions(Consumer<Expression> visitor) {
if (action != Action.OPTIONS) {
if (action != ForeignObjectAlterAction.OPTIONS) {
return;
}
super.visitExpressions(visitor);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*-
* #%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.alter;

/** Shared operations for ALTER SERVER and ALTER FOREIGN DATA WRAPPER. */
public enum ForeignObjectAlterAction {
/** Changes options and the object's server version or wrapper functions, when supplied. */
OPTIONS, OWNER, RENAME
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ public enum EnableState {
ENABLE, DISABLE, ENABLE_ALWAYS, ENABLE_REPLICA
}

/** Compatibility names for existing trigger clients. */
public enum TriggerState {
ENABLE, DISABLE, ENABLE_ALWAYS, ENABLE_REPLICA
}
public enum TriggerTarget {
NAME, ALL, USER
}
Expand All @@ -79,14 +75,6 @@ public void setEnableState(EnableState state) {
enableState = state;
}

public TriggerState getTriggerState() {
return enableState == null ? null : TriggerState.valueOf(enableState.name());
}

public void setTriggerState(TriggerState state) {
enableState = state == null ? null : EnableState.valueOf(state.name());
}

public TriggerTarget getTriggerTarget() {
return triggerTarget;
}
Expand Down
8 changes: 4 additions & 4 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -21293,9 +21293,9 @@ AlterForeignDataWrapper AlterForeignDataWrapper():
<K_FOREIGN> <K_DATA> ContextualKeyword("WRAPPER") name=RelObjectName() { statement.setName(name); }
(
<K_RENAME> <K_TO> name=RelObjectName()
{ statement.setAction(AlterForeignDataWrapper.Action.RENAME); statement.setNewName(name); }
{ statement.setAction(ForeignObjectAlterAction.RENAME); statement.setNewName(name); }
| LOOKAHEAD({ isKeywordAhead("OWNER") }) ContextualKeyword("OWNER") <K_TO> name=RelObjectName()
{ statement.setAction(AlterForeignDataWrapper.Action.OWNER); statement.setOwner(name); }
{ statement.setAction(ForeignObjectAlterAction.OWNER); statement.setOwner(name); }
| functions=ForeignDataWrapperFunctions() { statement.setFunctions(functions); }
[ LOOKAHEAD({ isKeywordAhead("OPTIONS") }) options=ForeignDataOptions(true) { statement.setOptions(options); } ]
{ requireDdlSyntax(functions.isHandlerSpecified() || functions.isValidatorSpecified()
Expand Down Expand Up @@ -21365,9 +21365,9 @@ AlterServer AlterServer():
ContextualKeyword("SERVER") name=RelObjectName() { statement.setName(name); }
(
<K_RENAME> <K_TO> name=RelObjectName()
{ statement.setAction(AlterServer.Action.RENAME); statement.setNewName(name); }
{ statement.setAction(ForeignObjectAlterAction.RENAME); statement.setNewName(name); }
| LOOKAHEAD({ isKeywordAhead("OWNER") }) ContextualKeyword("OWNER") <K_TO> name=RelObjectName()
{ statement.setAction(AlterServer.Action.OWNER); statement.setOwner(name); }
{ statement.setAction(ForeignObjectAlterAction.OWNER); statement.setOwner(name); }
| [ <K_VERSION> version=ForeignServerVersion() { statement.setVersion(version); } ]
[ LOOKAHEAD({ isKeywordAhead("OPTIONS") }) options=ForeignDataOptions(true) { statement.setOptions(options); } ]
{ requireDdlSyntax(statement.getVersion() != null || statement.getOptions() != null,
Expand Down
45 changes: 45 additions & 0 deletions src/site/sphinx/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,51 @@ References: `CREATE ROLE <https://www.postgresql.org/docs/18/sql-createrole.html
`ALTER DEFAULT PRIVILEGES <https://www.postgresql.org/docs/18/sql-alterdefaultprivileges.html>`_,
`CREATE TRIGGER <https://www.postgresql.org/docs/18/sql-createtrigger.html>`_.

Migrating shared ALTER enums
----------------------------

``AlterServer.Action`` and ``AlterForeignDataWrapper.Action`` have been replaced
by ``ForeignObjectAlterAction`` in ``net.sf.jsqlparser.statement.alter``. Both
statements' ``getAction()`` and ``setAction()`` now use this enum, with the same
``OPTIONS``, ``OWNER`` and ``RENAME`` constants. Update imports and recompile code
using these APIs; the removed nested enums are not compatibility aliases.

.. code-block:: java

AlterServer server = (AlterServer) CCJSqlParserUtil.parse(
"ALTER SERVER s VERSION NULL");
server.setAction(ForeignObjectAlterAction.OWNER);
server.setOwner("CURRENT_USER");
// ALTER SERVER s OWNER TO CURRENT_USER

AlterForeignDataWrapper wrapper = (AlterForeignDataWrapper) CCJSqlParserUtil.parse(
"ALTER FOREIGN DATA WRAPPER w NO HANDLER");
wrapper.setAction(ForeignObjectAlterAction.OWNER);
wrapper.setOwner("CURRENT_USER");
// ALTER FOREIGN DATA WRAPPER w OWNER TO CURRENT_USER

``OPTIONS`` remains the initial action. It includes server ``VERSION`` changes
and wrapper handler/validator changes as well as foreign-data options. These
payloads remain on their respective statement classes. Switching to ``OWNER`` or
``RENAME`` leaves the inactive payload available for switching back to ``OPTIONS``.

``RelationAlterAction.TriggerState``, ``getTriggerState()`` and
``setTriggerState()`` have been removed. Use the existing
``RelationAlterAction.EnableState``, ``getEnableState()`` and ``setEnableState()``
for both trigger and rewrite-rule actions:

.. code-block:: java

Alter alter = (Alter) CCJSqlParserUtil.parse(
"ALTER TABLE t ENABLE REPLICA TRIGGER trg",
parser -> parser.withDialect(Dialect.POSTGRESQL));
RelationAlterAction trigger = (RelationAlterAction) alter.getAlterExpressions().get(0);
trigger.setEnableState(RelationAlterAction.EnableState.DISABLE);
// ALTER TABLE t DISABLE TRIGGER trg

The action's ``Kind`` still distinguishes ``TRIGGER_STATE`` from ``RULE_STATE``.
Trigger targets also retain their ``NAME``, ``ALL`` and ``USER`` distinctions.

Oracle anonymous blocks
-----------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ void objectBoundariesAreEnforced(String sql) {
void triggerTargetsAndTypeNamesAreMutableWithoutInventingTables() throws JSQLParserException {
Alter statement = (Alter) parse("ALTER TABLE t ENABLE REPLICA TRIGGER trg");
RelationAlterAction action = (RelationAlterAction) statement.getAlterExpressions().get(0);
assertEquals(RelationAlterAction.TriggerState.ENABLE_REPLICA, action.getTriggerState());
action.setTriggerState(RelationAlterAction.TriggerState.DISABLE);
assertEquals(RelationAlterAction.EnableState.ENABLE_REPLICA, action.getEnableState());
action.setEnableState(RelationAlterAction.EnableState.DISABLE);
action.setTriggerTarget(RelationAlterAction.TriggerTarget.USER);
assertEquals("ALTER TABLE t DISABLE TRIGGER USER", statement.toString());
assertRoundTrip(statement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,20 @@ void ruleAndTriggerActionsShareStates(String state) throws JSQLParserException {
p -> p.withDialect(Dialect.POSTGRESQL));
RelationAlterAction triggerAction =
(RelationAlterAction) trigger.getAlterExpressions().get(0);
assertEquals(state.replace(' ', '_'), triggerAction.getTriggerState().name());
triggerAction.setTriggerState(RelationAlterAction.TriggerState.ENABLE_ALWAYS);
assertEquals(state.replace(' ', '_'), triggerAction.getEnableState().name());
triggerAction.setEnableState(null);
assertNull(triggerAction.getEnableState());
assertEquals(RelationAlterAction.Kind.TRIGGER_STATE, triggerAction.getKind());
assertEquals(RelationAlterAction.TriggerTarget.NAME, triggerAction.getTriggerTarget());
assertEquals("trg", triggerAction.getValue());
triggerAction.setEnableState(RelationAlterAction.EnableState.ENABLE_ALWAYS);
assertEquals(RelationAlterAction.EnableState.ENABLE_ALWAYS, triggerAction.getEnableState());
StringBuilder triggerSql = new StringBuilder();
trigger.accept(new StatementDeParser(triggerSql));
assertEquals("ALTER TABLE t ENABLE ALWAYS TRIGGER trg", triggerSql.toString());
assertEquals(trigger.toString(), triggerSql.toString());
assertEquals(triggerSql.toString(), CCJSqlParserUtil.parse(triggerSql.toString(),
p -> p.withDialect(Dialect.POSTGRESQL)).toString());
assertEquals(2, CCJSqlParserUtil.parseStatements(rule + "; SELECT 1").size());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.sf.jsqlparser.statement.alter.AlterForeignDataWrapper;
import net.sf.jsqlparser.statement.alter.AlterServer;
import net.sf.jsqlparser.statement.alter.AlterUserMapping;
import net.sf.jsqlparser.statement.alter.ForeignObjectAlterAction;
import net.sf.jsqlparser.statement.create.fdw.CreateForeignDataWrapper;
import net.sf.jsqlparser.statement.create.server.CreateServer;
import net.sf.jsqlparser.statement.create.table.ForeignDataOption;
Expand Down Expand Up @@ -102,14 +103,79 @@ void serverLiteralsAndOptionsAreVisitedAndMutable() throws JSQLParserException {
roundTrip(create);
AlterServer alter = (AlterServer) CCJSqlParserUtil.parse("ALTER SERVER s VERSION NULL");
assertInstanceOf(NullValue.class, alter.getVersion());
alter.setAction(AlterServer.Action.RENAME);
alter.setAction(ForeignObjectAlterAction.RENAME);
alter.setNewName("new_server");
visited.clear();
alter.visitExpressions(visited::add);
assertTrue(visited.isEmpty());
assertEquals("ALTER SERVER s RENAME TO new_server", alter.toString());
}

@Test
void sharedActionsKeepObjectSpecificOptionsInactiveAndRestorable() throws JSQLParserException {
AlterServer server = (AlterServer) CCJSqlParserUtil.parse(
"ALTER SERVER s VERSION NULL OPTIONS(SET host 'remote')");
AlterForeignDataWrapper wrapper = (AlterForeignDataWrapper) CCJSqlParserUtil.parse(
"ALTER FOREIGN DATA WRAPPER w NO HANDLER VALIDATOR public.validator "
+ "OPTIONS(SET x 'y')");
assertEquals(ForeignObjectAlterAction.OPTIONS, server.getAction());
assertSame(server.getAction(), wrapper.getAction());
String serverOptions = server.toString();
String wrapperOptions = wrapper.toString();

server.setOwner("CURRENT_ROLE");
wrapper.setOwner("CURRENT_USER");
server.setAction(ForeignObjectAlterAction.OWNER);
wrapper.setAction(ForeignObjectAlterAction.OWNER);
assertEquals("ALTER SERVER s OWNER TO CURRENT_ROLE", server.toString());
assertEquals("ALTER FOREIGN DATA WRAPPER w OWNER TO CURRENT_USER", wrapper.toString());
roundTrip(server);
roundTrip(wrapper);

server.setNewName("\"new server\"");
wrapper.setNewName("\"new wrapper\"");
server.setAction(ForeignObjectAlterAction.RENAME);
wrapper.setAction(ForeignObjectAlterAction.RENAME);
assertEquals("ALTER SERVER s RENAME TO \"new server\"", server.toString());
assertEquals("ALTER FOREIGN DATA WRAPPER w RENAME TO \"new wrapper\"", wrapper.toString());
roundTrip(server);
roundTrip(wrapper);

List<Expression> visited = new ArrayList<>();
server.visitExpressions(visited::add);
wrapper.visitExpressions(visited::add);
assertTrue(visited.isEmpty());
server.setAction(null);
wrapper.setAction(null);
assertNull(server.getAction());
assertNull(wrapper.getAction());
server.visitExpressions(visited::add);
wrapper.visitExpressions(visited::add);
assertTrue(visited.isEmpty());

server.setAction(ForeignObjectAlterAction.OPTIONS);
wrapper.setAction(ForeignObjectAlterAction.OPTIONS);
assertEquals(serverOptions, server.toString());
assertEquals(wrapperOptions, wrapper.toString());
server.visitExpressions(visited::add);
wrapper.visitExpressions(visited::add);
assertEquals(List.of(server.getOptions().get(0).getValue(), server.getVersion(),
wrapper.getOptions().get(0).getValue()), visited);
assertInstanceOf(NullValue.class, server.getVersion());
assertTrue(wrapper.getFunctions().isHandlerSpecified());
assertNull(wrapper.getFunctions().getHandler());
roundTrip(server);
roundTrip(wrapper);

server.setVersion(null);
wrapper.getFunctions().clearHandler();
assertEquals("ALTER SERVER s OPTIONS (SET host 'remote')", server.toString());
assertEquals("ALTER FOREIGN DATA WRAPPER w VALIDATOR public.validator OPTIONS (SET x 'y')",
wrapper.toString());
roundTrip(server);
roundTrip(wrapper);
}

@Test
void userMappingOptionsUseExistingForeignDataNodes() throws JSQLParserException {
CreateUserMapping create = (CreateUserMapping) CCJSqlParserUtil.parse(
Expand Down
Loading