Skip to content

Commit 18eafaf

Browse files
committed
Merge origin/master into fix/mysql-column-type-modifiers
2 parents 5154a9f + 2243e2b commit 18eafaf

6 files changed

Lines changed: 170 additions & 18 deletions

File tree

src/main/java/net/sf/jsqlparser/statement/create/table/CheckConstraint.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ public void setEnforced(Boolean enforced) {
5050
@Override
5151
public String toString() {
5252
StringBuilder b = new StringBuilder();
53-
if (getName() != null) {
54-
b.append("CONSTRAINT ").append(getName()).append(" ");
53+
if (isUseConstraintKeyword() || getName() != null) {
54+
b.append("CONSTRAINT");
55+
if (getName() != null) {
56+
b.append(" ").append(getName());
57+
}
58+
b.append(" ");
5559
}
5660
b.append("CHECK (").append(expression).append(")");
5761
if (enforced != null) {
@@ -89,6 +93,11 @@ public CheckConstraint withUsing(String using) {
8993
return (CheckConstraint) super.withUsing(using);
9094
}
9195

96+
@Override
97+
public CheckConstraint withUseConstraintKeyword(boolean useConstraintKeyword) {
98+
return (CheckConstraint) super.withUseConstraintKeyword(useConstraintKeyword);
99+
}
100+
92101
@Override
93102
public CheckConstraint withName(List<String> name) {
94103
return (CheckConstraint) super.withName(name);

src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ public ForeignKeyIndex withUsing(String using) {
169169
return (ForeignKeyIndex) super.withUsing(using);
170170
}
171171

172+
@Override
173+
public ForeignKeyIndex withIndexName(String indexName) {
174+
return (ForeignKeyIndex) super.withIndexName(indexName);
175+
}
176+
177+
@Override
178+
public ForeignKeyIndex withUseConstraintKeyword(boolean useConstraintKeyword) {
179+
return (ForeignKeyIndex) super.withUseConstraintKeyword(useConstraintKeyword);
180+
}
181+
172182
@Override
173183
public ForeignKeyIndex withName(List<String> name) {
174184
return (ForeignKeyIndex) super.withName(name);

src/main/java/net/sf/jsqlparser/statement/create/table/NamedConstraint.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,55 @@
1616

1717
public class NamedConstraint extends Index {
1818

19+
private String indexName;
20+
private boolean useConstraintKeyword;
21+
22+
/**
23+
* Returns the optional index name declared after the constraint type. This is distinct from
24+
* {@link #getName()}, which represents the optional constraint symbol.
25+
*
26+
* @return the index name, or {@code null} when it was omitted
27+
*/
28+
public String getIndexName() {
29+
return indexName;
30+
}
31+
32+
public void setIndexName(String indexName) {
33+
this.indexName = indexName;
34+
}
35+
36+
public boolean isUseConstraintKeyword() {
37+
return useConstraintKeyword;
38+
}
39+
40+
public void setUseConstraintKeyword(boolean useConstraintKeyword) {
41+
this.useConstraintKeyword = useConstraintKeyword;
42+
}
43+
1944
@Override
2045
public String toString() {
2146
String idxSpecText = PlainSelect.getStringList(getIndexSpec(), false, false);
22-
String head = getName() != null ? "CONSTRAINT " + getName() + " " : "";
23-
String tail = getType() + " " + PlainSelect.getStringList(getColumnsNames(), true, true) +
47+
String head = useConstraintKeyword || getName() != null
48+
? "CONSTRAINT" + (getName() != null ? " " + getName() : "") + " "
49+
: "";
50+
String tail = getType()
51+
+ (indexName != null ? " " + indexName : "")
52+
+ (getUsing() != null ? " USING " + getUsing() : "")
53+
+ " " + PlainSelect.getStringList(getColumnsNames(), true, true) +
2454
(!"".equals(idxSpecText) ? " " + idxSpecText : "");
2555
return head + tail;
2656
}
2757

58+
public NamedConstraint withIndexName(String indexName) {
59+
setIndexName(indexName);
60+
return this;
61+
}
62+
63+
public NamedConstraint withUseConstraintKeyword(boolean useConstraintKeyword) {
64+
setUseConstraintKeyword(useConstraintKeyword);
65+
return this;
66+
}
67+
2868
@Override
2969
public NamedConstraint withName(List<String> name) {
3070
return (NamedConstraint) super.withName(name);

src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11529,6 +11529,9 @@ Index CreateTableConstraint():
1152911529
Token tk2 = null;
1153011530
Token tk3 = null;
1153111531
String sk3 = null;
11532+
String indexName = null;
11533+
String using = null;
11534+
boolean useConstraintKeyword = false;
1153211535
List<Index.ColumnParams> colNames = null;
1153311536
List<String> parameter = new ArrayList<String>();
1153411537
List<String> idxSpec = new ArrayList<String>();
@@ -11556,16 +11559,25 @@ Index CreateTableConstraint():
1155611559
{
1155711560
index = new NamedConstraint();
1155811561
tk2=null;
11562+
indexName=null;
11563+
using=null;
1155911564
idxSpec.clear();
1156011565
}
11561-
[ <K_CONSTRAINT> sk3=RelObjectName() {index.setName(sk3);} ]
11566+
[ <K_CONSTRAINT> { ((NamedConstraint) index).setUseConstraintKeyword(true); }
11567+
[ LOOKAHEAD({ getToken(1).kind != K_PRIMARY && getToken(1).kind != K_UNIQUE })
11568+
sk3=RelObjectName() {index.setName(sk3);} ]
11569+
]
1156211570
(
1156311571
tk=<K_PRIMARY> tk2=<K_KEY>
1156411572
|
11565-
tk=<K_UNIQUE> [ tk2=<K_KEY> ]
11573+
tk=<K_UNIQUE> [ LOOKAHEAD(2) (tk2=<K_KEY> | tk2=<K_INDEX>) ]
11574+
[ LOOKAHEAD(2, { getToken(1).kind != K_USING }) indexName=RelObjectName() ]
11575+
[ LOOKAHEAD(2) using=UsingIndexType() ]
1156611576
)
1156711577
{
1156811578
index.setType( tk.image + ( tk2!=null ? " " + tk2.image : "" ));
11579+
((NamedConstraint) index).setIndexName(indexName);
11580+
index.setUsing(using);
1156911581
tk2=null;
1157011582
}
1157111583
colNames = ColumnNamesWithParamsList()
@@ -11596,17 +11608,21 @@ Index CreateTableConstraint():
1159611608
)
1159711609
|
1159811610
LOOKAHEAD(3) (
11599-
{ sk3=null; }
11600-
[ <K_CONSTRAINT> sk3=RelObjectName() ]
11611+
{ sk3=null; useConstraintKeyword=false; }
11612+
[ <K_CONSTRAINT> { useConstraintKeyword=true; }
11613+
[ LOOKAHEAD({ getToken(1).kind != K_FOREIGN }) sk3=RelObjectName() ]
11614+
]
1160111615
fkIndex = ForeignKeySpec(sk3)
11602-
{ index = fkIndex; }
11616+
{ fkIndex.setUseConstraintKeyword(useConstraintKeyword); index = fkIndex; }
1160311617
)
1160411618
|
1160511619
LOOKAHEAD(3) (
11606-
{ sk3 = null; }
11607-
[ <K_CONSTRAINT> sk3 = RelObjectName() ]
11620+
{ sk3 = null; useConstraintKeyword=false; }
11621+
[ <K_CONSTRAINT> { useConstraintKeyword=true; }
11622+
[ LOOKAHEAD({ getToken(1).kind != K_CHECK }) sk3 = RelObjectName() ]
11623+
]
1160811624
checkCs = CheckConstraintSpec(sk3)
11609-
{ index = checkCs; }
11625+
{ checkCs.setUseConstraintKeyword(useConstraintKeyword); index = checkCs; }
1161011626
)
1161111627
|
1161211628
LOOKAHEAD(2) (
@@ -12094,6 +12110,7 @@ CheckConstraint CheckConstraintSpec(String constraintName):
1209412110
ForeignKeyIndex ForeignKeySpec(String constraintName):
1209512111
{
1209612112
ForeignKeyIndex fkIndex = new ForeignKeyIndex();
12113+
String indexName = null;
1209712114
Token tk;
1209812115
Token tk2;
1209912116
List<String> refColNames = null;
@@ -12102,6 +12119,7 @@ ForeignKeyIndex ForeignKeySpec(String constraintName):
1210212119
}
1210312120
{
1210412121
tk=<K_FOREIGN> tk2=<K_KEY>
12122+
[ LOOKAHEAD(2) indexName=RelObjectName() { fkIndex.setIndexName(indexName); } ]
1210512123
colNames = ColumnNamesWithParamsList()
1210612124
{
1210712125
if (constraintName != null) { fkIndex.setName(constraintName); }
@@ -13483,20 +13501,30 @@ AlterExpression AlterExpressionAddAlterModify():
1348313501
LOOKAHEAD(3) AlterExpressionColumnChanges(alterExp)
1348413502
|
1348513503
(
13486-
<K_UNIQUE>
13504+
<K_UNIQUE> { index = new Index().withType("UNIQUE"); }
1348713505
(
1348813506
(
13489-
<K_KEY> { alterExp.setUk(true); }
13490-
| <K_INDEX> { alterExp.setUk(false); }
13507+
tk2=<K_KEY> { alterExp.setUk(true); }
13508+
| tk2=<K_INDEX> { alterExp.setUk(false); }
1349113509
)
13492-
[ (tk=<S_IDENTIFIER> | tk=<S_QUOTED_IDENTIFIER>) { alterExp.setUkName(tk.image); } ]
13510+
[ (tk=<S_IDENTIFIER> | tk=<S_QUOTED_IDENTIFIER>) {
13511+
sk3 = tk.image;
13512+
alterExp.setUkName(sk3);
13513+
} ]
1349313514
|
1349413515
(tk=<S_IDENTIFIER> | tk=<S_QUOTED_IDENTIFIER>) {
13516+
sk3 = tk.image;
1349513517
alterExp.setUkTypeSpecified(false);
13496-
alterExp.setUkName(tk.image);
13518+
alterExp.setUkName(sk3);
1349713519
}
1349813520
)?
13499-
columnNames=ColumnsNamesList() { alterExp.setUkColumns(columnNames); }
13521+
columnNames=ColumnsNamesList() {
13522+
alterExp.setUkColumns(columnNames);
13523+
index.withIndexKeyword(tk2 != null ? tk2.image : null)
13524+
.withName(sk3)
13525+
.withColumnsNames(columnNames);
13526+
alterExp.setIndex(index);
13527+
}
1350013528
[
1350113529
AlterExpressionUsingIndex(alterExp)
1350213530
]

src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,28 @@ public void testAlterTableDropAndAddUniqueIndexWithAscendingColumns() throws Exc
600600
result.toString());
601601
}
602602

603+
@Test
604+
public void testAlterTableAddUniqueIndexWithCommentIssue2503() throws Exception {
605+
String sql = "ALTER TABLE `wxp_dm`.`xqgl_req_report` "
606+
+ "ADD UNIQUE INDEX `index2` (`report_name` ASC) USING BTREE COMMENT '唯一索引'";
607+
608+
Alter alter = (Alter) assertSqlCanBeParsedAndDeparsed(sql);
609+
AlterExpression alterExpression = alter.getAlterExpressions().get(0);
610+
Index index = alterExpression.getIndex();
611+
612+
assertNotNull(index);
613+
assertEquals("UNIQUE", index.getType());
614+
assertEquals("INDEX", index.getIndexKeyword());
615+
assertEquals("`index2`", index.getName());
616+
assertEquals(List.of("`report_name` ASC"), index.getColumnsNames());
617+
assertEquals("'唯一索引'", index.getCommentText());
618+
619+
// Keep the legacy fields populated for existing consumers.
620+
assertEquals("`index2`", alterExpression.getUkName());
621+
assertEquals(List.of("`report_name` ASC"), alterExpression.getUkColumns());
622+
assertEquals(List.of("USING", "BTREE"), alterExpression.getParameters());
623+
}
624+
603625
@Test
604626
public void testIssue259() throws JSQLParserException {
605627
assertSqlCanBeParsedAndDeparsed(

src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import static org.junit.jupiter.api.Assertions.assertEquals;
1515
import static org.junit.jupiter.api.Assertions.assertFalse;
1616
import static org.junit.jupiter.api.Assertions.assertNotNull;
17+
import static org.junit.jupiter.api.Assertions.assertNull;
1718
import static org.junit.jupiter.api.Assertions.assertTrue;
1819

1920
import java.io.BufferedReader;
@@ -38,7 +39,9 @@
3839
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
3940
import net.sf.jsqlparser.statement.create.table.CreateTable;
4041
import net.sf.jsqlparser.statement.create.table.ExcludeConstraint;
42+
import net.sf.jsqlparser.statement.create.table.ForeignKeyIndex;
4143
import net.sf.jsqlparser.statement.create.table.Index;
44+
import net.sf.jsqlparser.statement.create.table.NamedConstraint;
4245
import net.sf.jsqlparser.statement.create.table.PartitionBound;
4346
import net.sf.jsqlparser.statement.create.table.RowMovementMode;
4447
import net.sf.jsqlparser.statement.create.table.TablePartitioning;
@@ -1275,6 +1278,46 @@ void testMySqlColumnTypeModifiers() throws JSQLParserException {
12751278
createTable.getColumnDefinitions().get(2).getColumnSpecs());
12761279
}
12771280

1281+
@Test
1282+
void testMySqlConstraintSymbolAndIndexNameIssue1570() throws JSQLParserException {
1283+
String uniqueSql = "CREATE TABLE table1 (col1 INT, col2 INT UNIQUE, "
1284+
+ "CONSTRAINT my_constraint UNIQUE KEY index_name (col1))";
1285+
CreateTable uniqueTable = (CreateTable) assertSqlCanBeParsedAndDeparsed(uniqueSql, true);
1286+
NamedConstraint unique = (NamedConstraint) uniqueTable.getIndexes().get(0);
1287+
1288+
assertEquals("my_constraint", unique.getName());
1289+
assertEquals("index_name", unique.getIndexName());
1290+
assertEquals("UNIQUE KEY", unique.getType());
1291+
1292+
String foreignKeySql = "CREATE TABLE table2 (id INT, parent_id INT, "
1293+
+ "CONSTRAINT fk_parent FOREIGN KEY fk_parent_idx (parent_id) "
1294+
+ "REFERENCES parent (id))";
1295+
CreateTable foreignKeyTable =
1296+
(CreateTable) assertSqlCanBeParsedAndDeparsed(foreignKeySql, true);
1297+
ForeignKeyIndex foreignKey = (ForeignKeyIndex) foreignKeyTable.getIndexes().get(0);
1298+
1299+
assertEquals("fk_parent", foreignKey.getName());
1300+
assertEquals("fk_parent_idx", foreignKey.getIndexName());
1301+
}
1302+
1303+
@Test
1304+
void testMySqlUnnamedConstraintAndUniqueIndexOptionsIssues1570And538()
1305+
throws JSQLParserException {
1306+
assertSqlCanBeParsedAndDeparsed(
1307+
"CREATE TABLE table1 (col1 INT, CONSTRAINT UNIQUE KEY (col1))", true);
1308+
1309+
String sql = "CREATE TABLE g_platform_payway (id INT, platform_code VARCHAR (45), "
1310+
+ "pay_way VARCHAR (32), UNIQUE uniq_platform_payway USING BTREE "
1311+
+ "(platform_code, pay_way) COMMENT 'should be unique')";
1312+
CreateTable createTable = (CreateTable) assertSqlCanBeParsedAndDeparsed(sql, true);
1313+
NamedConstraint unique = (NamedConstraint) createTable.getIndexes().get(0);
1314+
1315+
assertNull(unique.getName());
1316+
assertEquals("uniq_platform_payway", unique.getIndexName());
1317+
assertEquals("BTREE", unique.getUsing());
1318+
assertEquals(List.of("COMMENT", "'should be unique'"), unique.getIndexSpec());
1319+
}
1320+
12781321
@Test
12791322
void testPostgreSqlDeclarativePartitionParentsIssue2522() throws JSQLParserException {
12801323
String sql = "CREATE TABLE pg_range_parent (tenant_id int, "

0 commit comments

Comments
 (0)