Skip to content

Commit 050bc8c

Browse files
committed
Support structured PostgreSQL logical replication DDL
1 parent 6c726d8 commit 050bc8c

21 files changed

Lines changed: 1558 additions & 1 deletion

File tree

src/main/java/net/sf/jsqlparser/parser/feature/Feature.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ public enum Feature {
559559
* @see CreateSequence
560560
*/
561561
createSequence,
562+
/** Publication and subscription definitions. */
563+
createPublication, alterPublication, createSubscription, alterSubscription,
562564
/**
563565
* SQL "CREATE SYNONYM" statement is allowed
564566
*

src/main/java/net/sf/jsqlparser/statement/StatementFeatureVisitor.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
*/
1010
package net.sf.jsqlparser.statement;
1111

12+
import net.sf.jsqlparser.statement.create.publication.CreatePublication;
13+
import net.sf.jsqlparser.statement.alter.AlterPublication;
14+
import net.sf.jsqlparser.statement.create.subscription.CreateSubscription;
15+
import net.sf.jsqlparser.statement.create.subscription.SubscriptionOption;
16+
import net.sf.jsqlparser.statement.alter.AlterSubscription;
17+
1218
import net.sf.jsqlparser.JSQLParserException;
1319
import net.sf.jsqlparser.expression.Expression;
1420
import net.sf.jsqlparser.expression.ExpressionVisitor;
@@ -846,4 +852,48 @@ public <S> Void visit(TableFunction tableFunction, S context) {
846852
return super.visit(tableFunction, context);
847853
}
848854
}
855+
856+
@Override
857+
public <S> Void visit(CreatePublication statement, S context) {
858+
analysis.claimTopLevel();
859+
analysis.certain(StmtFeature.MODIFIES_SCHEMA);
860+
861+
return null;
862+
}
863+
864+
@Override
865+
public <S> Void visit(AlterPublication statement, S context) {
866+
analysis.claimTopLevel();
867+
analysis.certain(StmtFeature.MODIFIES_SCHEMA);
868+
869+
return null;
870+
}
871+
872+
@Override
873+
public <S> Void visit(CreateSubscription statement, S context) {
874+
analysis.claimTopLevel();
875+
analysis.certain(StmtFeature.MODIFIES_SCHEMA);
876+
if (statement.getOptions().stream()
877+
.noneMatch(option -> (option.getKind() == SubscriptionOption.Kind.CONNECT
878+
|| option.getKind() == SubscriptionOption.Kind.ENABLED)
879+
&& Boolean.FALSE.equals(option.getBooleanValue()))) {
880+
// A subscription may start asynchronous replication; the remote contents are unknown.
881+
analysis.possible(StmtFeature.MODIFIES_DATA);
882+
}
883+
return null;
884+
}
885+
886+
@Override
887+
public <S> Void visit(AlterSubscription statement, S context) {
888+
analysis.claimTopLevel();
889+
analysis.certain(StmtFeature.MODIFIES_SCHEMA);
890+
if (statement.getAction() == AlterSubscription.Action.ENABLE
891+
|| statement.getAction() == AlterSubscription.Action.REFRESH_PUBLICATION
892+
|| statement.getAction() == AlterSubscription.Action.SET_PUBLICATION
893+
|| statement.getAction() == AlterSubscription.Action.ADD_PUBLICATION
894+
|| statement.getAction() == AlterSubscription.Action.DROP_PUBLICATION) {
895+
analysis.possible(StmtFeature.MODIFIES_DATA);
896+
}
897+
return null;
898+
}
849899
}

src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
*/
1010
package net.sf.jsqlparser.statement;
1111

12+
import net.sf.jsqlparser.statement.create.publication.CreatePublication;
13+
import net.sf.jsqlparser.statement.alter.AlterPublication;
14+
import net.sf.jsqlparser.statement.create.subscription.CreateSubscription;
15+
import net.sf.jsqlparser.statement.alter.AlterSubscription;
16+
1217
import net.sf.jsqlparser.statement.alter.Alter;
1318
import net.sf.jsqlparser.statement.alter.AlterSession;
1419
import net.sf.jsqlparser.statement.alter.AlterSystemStatement;
@@ -393,4 +398,35 @@ default void visit(CreatePolicy createPolicy) {
393398
this.visit(createPolicy, null);
394399
}
395400

401+
default <S> T visit(CreatePublication statement, S context) {
402+
return null;
403+
}
404+
405+
default void visit(CreatePublication statement) {
406+
visit(statement, null);
407+
}
408+
409+
default <S> T visit(AlterPublication statement, S context) {
410+
return null;
411+
}
412+
413+
default void visit(AlterPublication statement) {
414+
visit(statement, null);
415+
}
416+
417+
default <S> T visit(CreateSubscription statement, S context) {
418+
return null;
419+
}
420+
421+
default void visit(CreateSubscription statement) {
422+
visit(statement, null);
423+
}
424+
425+
default <S> T visit(AlterSubscription statement, S context) {
426+
return null;
427+
}
428+
429+
default void visit(AlterSubscription statement) {
430+
visit(statement, null);
431+
}
396432
}

src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
*/
1010
package net.sf.jsqlparser.statement;
1111

12+
import net.sf.jsqlparser.statement.create.publication.CreatePublication;
13+
import net.sf.jsqlparser.statement.alter.AlterPublication;
14+
import net.sf.jsqlparser.statement.create.subscription.CreateSubscription;
15+
import net.sf.jsqlparser.statement.alter.AlterSubscription;
16+
1217
import net.sf.jsqlparser.expression.ExpressionVisitor;
1318
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
1419
import net.sf.jsqlparser.schema.Column;
@@ -596,4 +601,56 @@ public <S> T visit(Import imprt, S context) {
596601
public <S> T visit(Export export, S context) {
597602
return null;
598603
}
604+
605+
@Override
606+
public <S> T visit(CreatePublication statement, S context) {
607+
statement.getTargets().forEach(target -> target.visit(
608+
table -> table.accept(fromItemVisitor, context),
609+
expression -> expression.accept(expressionVisitor, context)));
610+
statement.getOptions().forEach(option -> {
611+
if (option.getValue() != null) {
612+
option.getValue().accept(expressionVisitor, context);
613+
}
614+
});
615+
return null;
616+
}
617+
618+
@Override
619+
public <S> T visit(AlterPublication statement, S context) {
620+
statement.getTargets().forEach(target -> target.visit(
621+
table -> table.accept(fromItemVisitor, context),
622+
expression -> expression.accept(expressionVisitor, context)));
623+
statement.getOptions().forEach(option -> {
624+
if (option.getValue() != null) {
625+
option.getValue().accept(expressionVisitor, context);
626+
}
627+
});
628+
return null;
629+
}
630+
631+
@Override
632+
public <S> T visit(CreateSubscription statement, S context) {
633+
if (statement.getConnection() != null) {
634+
statement.getConnection().accept(expressionVisitor, context);
635+
}
636+
statement.getOptions().forEach(option -> {
637+
if (option.getValue() != null) {
638+
option.getValue().accept(expressionVisitor, context);
639+
}
640+
});
641+
return null;
642+
}
643+
644+
@Override
645+
public <S> T visit(AlterSubscription statement, S context) {
646+
if (statement.getConnection() != null) {
647+
statement.getConnection().accept(expressionVisitor, context);
648+
}
649+
statement.getOptions().forEach(option -> {
650+
if (option.getValue() != null) {
651+
option.getValue().accept(expressionVisitor, context);
652+
}
653+
});
654+
return null;
655+
}
599656
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.alter;
11+
12+
import java.util.ArrayList;
13+
import java.util.List;
14+
import java.util.function.Consumer;
15+
import net.sf.jsqlparser.expression.Expression;
16+
import net.sf.jsqlparser.statement.create.publication.PublicationTarget;
17+
import net.sf.jsqlparser.statement.create.publication.PublicationOption;
18+
import net.sf.jsqlparser.statement.Statement;
19+
import net.sf.jsqlparser.statement.StatementVisitor;
20+
21+
public class AlterPublication implements Statement {
22+
private String name;
23+
private Action action;
24+
private List<PublicationTarget> targets = new ArrayList<>();
25+
private List<PublicationOption> options = new ArrayList<>();
26+
private String newName;
27+
28+
public String getName() {
29+
return name;
30+
}
31+
32+
public void setName(String name) {
33+
this.name = name;
34+
}
35+
36+
public Action getAction() {
37+
return action;
38+
}
39+
40+
public void setAction(Action action) {
41+
this.action = action;
42+
}
43+
44+
public List<PublicationTarget> getTargets() {
45+
return targets;
46+
}
47+
48+
public void setTargets(List<PublicationTarget> targets) {
49+
this.targets = targets;
50+
}
51+
52+
public List<PublicationOption> getOptions() {
53+
return options;
54+
}
55+
56+
public void setOptions(List<PublicationOption> options) {
57+
this.options = options;
58+
}
59+
60+
public String getNewName() {
61+
return newName;
62+
}
63+
64+
public void setNewName(String newName) {
65+
this.newName = newName;
66+
}
67+
68+
@Override
69+
public <T, S> T accept(StatementVisitor<T> visitor, S context) {
70+
return visitor.visit(this, context);
71+
}
72+
73+
public enum Action {
74+
ADD, SET, DROP, SET_OPTIONS, OWNER, RENAME
75+
}
76+
77+
public void appendTo(StringBuilder sql, Consumer<Expression> expressions) {
78+
sql.append("ALTER PUBLICATION ").append(name).append(' ');
79+
switch (action) {
80+
case OWNER:
81+
sql.append("OWNER TO ").append(newName);
82+
break;
83+
case RENAME:
84+
sql.append("RENAME TO ").append(newName);
85+
break;
86+
case SET_OPTIONS:
87+
sql.append("SET (");
88+
for (int i = 0; i < options.size(); i++) {
89+
if (i > 0) {
90+
sql.append(", ");
91+
}
92+
options.get(i).appendTo(sql, expressions);
93+
}
94+
sql.append(')');
95+
break;
96+
case ADD:
97+
case SET:
98+
case DROP:
99+
sql.append(action).append(' ');
100+
for (int i = 0; i < targets.size(); i++) {
101+
if (i > 0) {
102+
sql.append(", ");
103+
}
104+
targets.get(i).appendTo(sql, expressions);
105+
}
106+
break;
107+
default:
108+
throw new IllegalStateException("Unknown publication alteration: " + action);
109+
}
110+
}
111+
112+
@Override
113+
public String toString() {
114+
StringBuilder sql = new StringBuilder();
115+
appendTo(sql, sql::append);
116+
return sql.toString();
117+
}
118+
}

0 commit comments

Comments
 (0)