Skip to content

Commit d2769be

Browse files
authored
feat: parse PostgreSQL CREATE CAST, CREATE TRANSFORM, CREATE CONVERSION and ALTER CONVERSION (#2918)
CREATE CAST (source AS target) WITH FUNCTION f(args) | WITHOUT FUNCTION | WITH INOUT [AS ASSIGNMENT | AS IMPLICIT], CREATE [OR REPLACE] TRANSFORM FOR type LANGUAGE lang (FROM SQL WITH FUNCTION f, TO SQL WITH FUNCTION g), CREATE [DEFAULT] CONVERSION name FOR 'enc' TO 'enc' FROM function and ALTER CONVERSION name RENAME TO | OWNER TO | SET SCHEMA were unsupported statements. They parse to CreateCast, CreateTransform, CreateConversion and AlterConversion. A cast and a transform are named by the CastSignature and TransformSignature of DROP CAST and DROP TRANSFORM, and functions are RoutineReference objects, read by the existing productions. The statements are wired into the deparser, visitors, table finder, validation (createCast, createTransform, createConversion and alterConversion, enabled for PostgreSQL) and feature analysis. With the PostgreSQL dialect these words start only these statements, so forms the server reports as syntax errors are parse errors. In another dialect and without one, a statement is read this way when it has PostgreSQL's form, and statements of other products that start with the same words, such as CREATE CAST (a AS b) WITH SPECIFIC FUNCTION f, stay unsupported statements. Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent dd63575 commit d2769be

21 files changed

Lines changed: 1562 additions & 5 deletions

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ and missing syntax gets added on demand — [open an issue](https://github.com/J
167167
| **MySQL utility statements** | `EXPLAIN`/`DESCRIBE [ANALYZE] FORMAT = …` · `EXPLAIN FOR CONNECTION` · `DESCRIBE t col` · `PREPARE … FROM` · `EXECUTE … USING` · `DROP PREPARE` · `DO` |
168168
| **PostgreSQL administration** | `CREATE`/`ALTER EVENT TRIGGER` · `REINDEX` · `SECURITY LABEL` |
169169
| **PostgreSQL types and rules** | `CREATE TYPE` (shell, composite, enum, range and base types) · `ALTER TYPE` · `CREATE RULE` · `ALTER RULE` |
170+
| **PostgreSQL casts, transforms and conversions** | `CREATE CAST` · `DROP CAST` · `CREATE [OR REPLACE] TRANSFORM` · `DROP TRANSFORM` · `CREATE [DEFAULT] CONVERSION` · `ALTER CONVERSION` |
170171
| **PostgreSQL operators and aggregates** | `CREATE`/`ALTER OPERATOR` · `CREATE`/`ALTER OPERATOR CLASS` · `CREATE`/`ALTER OPERATOR FAMILY` · `CREATE`/`ALTER AGGREGATE` |
171172
| **Informix constraints** | `ALTER TABLE … ADD CONSTRAINT` with trailing constraint names for primary, unique, foreign and check constraints; enable with `parser.withDialect(Dialect.INFORMIX)` |
172173
| **Salesforce SOQL** | `INCLUDES` · `EXCLUDES` |

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,30 @@ public enum Feature {
10361036
* @see net.sf.jsqlparser.statement.alter.AlterRule
10371037
*/
10381038
alterRule,
1039+
/**
1040+
* PostgreSQL "CREATE CAST" statement is allowed
1041+
*
1042+
* @see net.sf.jsqlparser.statement.create.cast.CreateCast
1043+
*/
1044+
createCast,
1045+
/**
1046+
* PostgreSQL "CREATE TRANSFORM" statement is allowed
1047+
*
1048+
* @see net.sf.jsqlparser.statement.create.transform.CreateTransform
1049+
*/
1050+
createTransform,
1051+
/**
1052+
* PostgreSQL "CREATE CONVERSION" statement is allowed
1053+
*
1054+
* @see net.sf.jsqlparser.statement.create.conversion.CreateConversion
1055+
*/
1056+
createConversion,
1057+
/**
1058+
* PostgreSQL "ALTER CONVERSION" statement is allowed
1059+
*
1060+
* @see net.sf.jsqlparser.statement.alter.AlterConversion
1061+
*/
1062+
alterConversion,
10391063
/**
10401064
* PostgreSQL "CREATE OPERATOR" statement is allowed
10411065
*

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
import net.sf.jsqlparser.statement.alter.AlterOperatorFamily;
4646
import net.sf.jsqlparser.statement.alter.AlterAggregate;
4747
import net.sf.jsqlparser.statement.alter.AlterRule;
48+
import net.sf.jsqlparser.statement.create.cast.CreateCast;
49+
import net.sf.jsqlparser.statement.create.transform.CreateTransform;
50+
import net.sf.jsqlparser.statement.create.conversion.CreateConversion;
51+
import net.sf.jsqlparser.statement.alter.AlterConversion;
4852
import net.sf.jsqlparser.statement.alter.AlterServer;
4953
import net.sf.jsqlparser.statement.alter.AlterSession;
5054
import net.sf.jsqlparser.statement.alter.AlterStatistics;
@@ -1631,21 +1635,41 @@ public <S> Void visit(AlterRule statement, S context) {
16311635
return schemaOnly();
16321636
}
16331637

1638+
@Override
1639+
public <S> Void visit(CreateCast statement, S context) {
1640+
return schemaOnly();
1641+
}
1642+
16341643
@Override
16351644
public <S> Void visit(CreateOperator statement, S context) {
16361645
return schemaOnly();
16371646
}
16381647

1648+
@Override
1649+
public <S> Void visit(CreateTransform statement, S context) {
1650+
return schemaOnly();
1651+
}
1652+
16391653
@Override
16401654
public <S> Void visit(CreateOperatorClass statement, S context) {
16411655
return schemaOnly();
16421656
}
16431657

1658+
@Override
1659+
public <S> Void visit(CreateConversion statement, S context) {
1660+
return schemaOnly();
1661+
}
1662+
16441663
@Override
16451664
public <S> Void visit(CreateOperatorFamily statement, S context) {
16461665
return schemaOnly();
16471666
}
16481667

1668+
@Override
1669+
public <S> Void visit(AlterConversion statement, S context) {
1670+
return schemaOnly();
1671+
}
1672+
16491673
@Override
16501674
public <S> Void visit(CreateAggregate statement, S context) {
16511675
return schemaOnly();

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
import net.sf.jsqlparser.statement.alter.AlterOperatorFamily;
3434
import net.sf.jsqlparser.statement.alter.AlterAggregate;
3535
import net.sf.jsqlparser.statement.alter.AlterRule;
36+
import net.sf.jsqlparser.statement.create.cast.CreateCast;
37+
import net.sf.jsqlparser.statement.create.transform.CreateTransform;
38+
import net.sf.jsqlparser.statement.create.conversion.CreateConversion;
39+
import net.sf.jsqlparser.statement.alter.AlterConversion;
3640
import net.sf.jsqlparser.statement.alter.AlterRoutine;
3741
import net.sf.jsqlparser.statement.alter.AlterTrigger;
3842
import net.sf.jsqlparser.statement.alter.AlterPolicy;
@@ -1262,6 +1266,38 @@ default void visit(AlterRule statement) {
12621266
visit(statement, null);
12631267
}
12641268

1269+
default <S> T visit(CreateCast statement, S context) {
1270+
return null;
1271+
}
1272+
1273+
default void visit(CreateCast statement) {
1274+
visit(statement, null);
1275+
}
1276+
1277+
default <S> T visit(CreateTransform statement, S context) {
1278+
return null;
1279+
}
1280+
1281+
default void visit(CreateTransform statement) {
1282+
visit(statement, null);
1283+
}
1284+
1285+
default <S> T visit(CreateConversion statement, S context) {
1286+
return null;
1287+
}
1288+
1289+
default void visit(CreateConversion statement) {
1290+
visit(statement, null);
1291+
}
1292+
1293+
default <S> T visit(AlterConversion statement, S context) {
1294+
return null;
1295+
}
1296+
1297+
default void visit(AlterConversion statement) {
1298+
visit(statement, null);
1299+
}
1300+
12651301
default <S> T visit(CreateOperator statement, S context) {
12661302
return null;
12671303
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
import net.sf.jsqlparser.statement.alter.AlterRelation;
1313
import net.sf.jsqlparser.statement.alter.AlterRule;
14+
import net.sf.jsqlparser.statement.create.cast.CreateCast;
15+
import net.sf.jsqlparser.statement.create.transform.CreateTransform;
16+
import net.sf.jsqlparser.statement.create.conversion.CreateConversion;
17+
import net.sf.jsqlparser.statement.alter.AlterConversion;
1418
import net.sf.jsqlparser.statement.alter.AlterTablespace;
1519
import net.sf.jsqlparser.statement.alter.AlterPolicy;
1620
import net.sf.jsqlparser.statement.alter.AlterRoutine;
@@ -1294,4 +1298,24 @@ public <S> T visit(AlterRule statement, S context) {
12941298
fromItemVisitor.visitFromItem(statement.getTable(), context);
12951299
return null;
12961300
}
1301+
1302+
@Override
1303+
public <S> T visit(CreateCast statement, S context) {
1304+
return null;
1305+
}
1306+
1307+
@Override
1308+
public <S> T visit(CreateTransform statement, S context) {
1309+
return null;
1310+
}
1311+
1312+
@Override
1313+
public <S> T visit(CreateConversion statement, S context) {
1314+
return null;
1315+
}
1316+
1317+
@Override
1318+
public <S> T visit(AlterConversion statement, S context) {
1319+
return null;
1320+
}
12971321
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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 net.sf.jsqlparser.parser.ASTNodeAccessImpl;
13+
import net.sf.jsqlparser.statement.Statement;
14+
import net.sf.jsqlparser.statement.StatementVisitor;
15+
16+
/**
17+
* PostgreSQL
18+
* {@code ALTER CONVERSION name {RENAME TO new_name | OWNER TO role | SET SCHEMA schema}}. Names
19+
* retain SQL identifier quoting.
20+
*/
21+
public class AlterConversion extends ASTNodeAccessImpl implements Statement {
22+
public enum Action {
23+
RENAME, OWNER, SET_SCHEMA
24+
}
25+
26+
private String name;
27+
private Action action;
28+
private String newName;
29+
private String owner;
30+
private String schemaName;
31+
32+
public String getName() {
33+
return name;
34+
}
35+
36+
public void setName(String name) {
37+
this.name = name;
38+
}
39+
40+
public AlterConversion withName(String name) {
41+
setName(name);
42+
return this;
43+
}
44+
45+
public Action getAction() {
46+
return action;
47+
}
48+
49+
public void setAction(Action action) {
50+
this.action = action;
51+
}
52+
53+
public AlterConversion withAction(Action action) {
54+
setAction(action);
55+
return this;
56+
}
57+
58+
public String getNewName() {
59+
return newName;
60+
}
61+
62+
public void setNewName(String newName) {
63+
this.newName = newName;
64+
}
65+
66+
public AlterConversion withNewName(String newName) {
67+
setNewName(newName);
68+
return this;
69+
}
70+
71+
/**
72+
* The new owner: a role name, {@code CURRENT_ROLE}, {@code CURRENT_USER} or
73+
* {@code SESSION_USER}.
74+
*
75+
* @return the owner of {@code OWNER TO}
76+
*/
77+
public String getOwner() {
78+
return owner;
79+
}
80+
81+
public void setOwner(String owner) {
82+
this.owner = owner;
83+
}
84+
85+
public AlterConversion withOwner(String owner) {
86+
setOwner(owner);
87+
return this;
88+
}
89+
90+
public String getSchemaName() {
91+
return schemaName;
92+
}
93+
94+
public void setSchemaName(String schemaName) {
95+
this.schemaName = schemaName;
96+
}
97+
98+
public AlterConversion withSchemaName(String schemaName) {
99+
setSchemaName(schemaName);
100+
return this;
101+
}
102+
103+
public StringBuilder appendTo(StringBuilder builder) {
104+
builder.append("ALTER CONVERSION ").append(name);
105+
switch (action) {
106+
case RENAME:
107+
builder.append(" RENAME TO ").append(newName);
108+
break;
109+
case OWNER:
110+
builder.append(" OWNER TO ").append(owner);
111+
break;
112+
case SET_SCHEMA:
113+
builder.append(" SET SCHEMA ").append(schemaName);
114+
break;
115+
default:
116+
throw new IllegalStateException("Unknown conversion action: " + action);
117+
}
118+
return builder;
119+
}
120+
121+
@Override
122+
public String toString() {
123+
return appendTo(new StringBuilder()).toString();
124+
}
125+
126+
@Override
127+
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
128+
return statementVisitor.visit(this, context);
129+
}
130+
}

0 commit comments

Comments
 (0)