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 @@ -50,8 +50,12 @@ public void setEnforced(Boolean enforced) {
@Override
public String toString() {
StringBuilder b = new StringBuilder();
if (getName() != null) {
b.append("CONSTRAINT ").append(getName()).append(" ");
if (isUseConstraintKeyword() || getName() != null) {
b.append("CONSTRAINT");
if (getName() != null) {
b.append(" ").append(getName());
}
b.append(" ");
}
b.append("CHECK (").append(expression).append(")");
if (enforced != null) {
Expand Down Expand Up @@ -89,6 +93,11 @@ public CheckConstraint withUsing(String using) {
return (CheckConstraint) super.withUsing(using);
}

@Override
public CheckConstraint withUseConstraintKeyword(boolean useConstraintKeyword) {
return (CheckConstraint) super.withUseConstraintKeyword(useConstraintKeyword);
}

@Override
public CheckConstraint withName(List<String> name) {
return (CheckConstraint) super.withName(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,16 @@ public ForeignKeyIndex withUsing(String using) {
return (ForeignKeyIndex) super.withUsing(using);
}

@Override
public ForeignKeyIndex withIndexName(String indexName) {
return (ForeignKeyIndex) super.withIndexName(indexName);
}

@Override
public ForeignKeyIndex withUseConstraintKeyword(boolean useConstraintKeyword) {
return (ForeignKeyIndex) super.withUseConstraintKeyword(useConstraintKeyword);
}

@Override
public ForeignKeyIndex withName(List<String> name) {
return (ForeignKeyIndex) super.withName(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,55 @@

public class NamedConstraint extends Index {

private String indexName;
private boolean useConstraintKeyword;

/**
* Returns the optional index name declared after the constraint type. This is distinct from
* {@link #getName()}, which represents the optional constraint symbol.
*
* @return the index name, or {@code null} when it was omitted
*/
public String getIndexName() {
return indexName;
}

public void setIndexName(String indexName) {
this.indexName = indexName;
}

public boolean isUseConstraintKeyword() {
return useConstraintKeyword;
}

public void setUseConstraintKeyword(boolean useConstraintKeyword) {
this.useConstraintKeyword = useConstraintKeyword;
}

@Override
public String toString() {
String idxSpecText = PlainSelect.getStringList(getIndexSpec(), false, false);
String head = getName() != null ? "CONSTRAINT " + getName() + " " : "";
String tail = getType() + " " + PlainSelect.getStringList(getColumnsNames(), true, true) +
String head = useConstraintKeyword || getName() != null
? "CONSTRAINT" + (getName() != null ? " " + getName() : "") + " "
: "";
String tail = getType()
+ (indexName != null ? " " + indexName : "")
+ (getUsing() != null ? " USING " + getUsing() : "")
+ " " + PlainSelect.getStringList(getColumnsNames(), true, true) +
(!"".equals(idxSpecText) ? " " + idxSpecText : "");
return head + tail;
}

public NamedConstraint withIndexName(String indexName) {
setIndexName(indexName);
return this;
}

public NamedConstraint withUseConstraintKeyword(boolean useConstraintKeyword) {
setUseConstraintKeyword(useConstraintKeyword);
return this;
}

@Override
public NamedConstraint withName(List<String> name) {
return (NamedConstraint) super.withName(name);
Expand Down
34 changes: 26 additions & 8 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -11446,6 +11446,9 @@ Index CreateTableConstraint():
Token tk2 = null;
Token tk3 = null;
String sk3 = null;
String indexName = null;
String using = null;
boolean useConstraintKeyword = false;
List<Index.ColumnParams> colNames = null;
List<String> parameter = new ArrayList<String>();
List<String> idxSpec = new ArrayList<String>();
Expand Down Expand Up @@ -11473,16 +11476,25 @@ Index CreateTableConstraint():
{
index = new NamedConstraint();
tk2=null;
indexName=null;
using=null;
idxSpec.clear();
}
[ <K_CONSTRAINT> sk3=RelObjectName() {index.setName(sk3);} ]
[ <K_CONSTRAINT> { ((NamedConstraint) index).setUseConstraintKeyword(true); }
[ LOOKAHEAD({ getToken(1).kind != K_PRIMARY && getToken(1).kind != K_UNIQUE })
sk3=RelObjectName() {index.setName(sk3);} ]
]
(
tk=<K_PRIMARY> tk2=<K_KEY>
|
tk=<K_UNIQUE> [ tk2=<K_KEY> ]
tk=<K_UNIQUE> [ LOOKAHEAD(2) (tk2=<K_KEY> | tk2=<K_INDEX>) ]
[ LOOKAHEAD(2, { getToken(1).kind != K_USING }) indexName=RelObjectName() ]
[ LOOKAHEAD(2) using=UsingIndexType() ]
)
{
index.setType( tk.image + ( tk2!=null ? " " + tk2.image : "" ));
((NamedConstraint) index).setIndexName(indexName);
index.setUsing(using);
tk2=null;
}
colNames = ColumnNamesWithParamsList()
Expand Down Expand Up @@ -11513,17 +11525,21 @@ Index CreateTableConstraint():
)
|
LOOKAHEAD(3) (
{ sk3=null; }
[ <K_CONSTRAINT> sk3=RelObjectName() ]
{ sk3=null; useConstraintKeyword=false; }
[ <K_CONSTRAINT> { useConstraintKeyword=true; }
[ LOOKAHEAD({ getToken(1).kind != K_FOREIGN }) sk3=RelObjectName() ]
]
fkIndex = ForeignKeySpec(sk3)
{ index = fkIndex; }
{ fkIndex.setUseConstraintKeyword(useConstraintKeyword); index = fkIndex; }
)
|
LOOKAHEAD(3) (
{ sk3 = null; }
[ <K_CONSTRAINT> sk3 = RelObjectName() ]
{ sk3 = null; useConstraintKeyword=false; }
[ <K_CONSTRAINT> { useConstraintKeyword=true; }
[ LOOKAHEAD({ getToken(1).kind != K_CHECK }) sk3 = RelObjectName() ]
]
checkCs = CheckConstraintSpec(sk3)
{ index = checkCs; }
{ checkCs.setUseConstraintKeyword(useConstraintKeyword); index = checkCs; }
)
|
LOOKAHEAD(2) (
Expand Down Expand Up @@ -11972,6 +11988,7 @@ CheckConstraint CheckConstraintSpec(String constraintName):
ForeignKeyIndex ForeignKeySpec(String constraintName):
{
ForeignKeyIndex fkIndex = new ForeignKeyIndex();
String indexName = null;
Token tk;
Token tk2;
List<String> refColNames = null;
Expand All @@ -11980,6 +11997,7 @@ ForeignKeyIndex ForeignKeySpec(String constraintName):
}
{
tk=<K_FOREIGN> tk2=<K_KEY>
[ LOOKAHEAD(2) indexName=RelObjectName() { fkIndex.setIndexName(indexName); } ]
colNames = ColumnNamesWithParamsList()
{
if (constraintName != null) { fkIndex.setName(constraintName); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.BufferedReader;
Expand All @@ -35,7 +36,9 @@
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.create.table.ExcludeConstraint;
import net.sf.jsqlparser.statement.create.table.ForeignKeyIndex;
import net.sf.jsqlparser.statement.create.table.Index;
import net.sf.jsqlparser.statement.create.table.NamedConstraint;
import net.sf.jsqlparser.statement.create.table.RowMovementMode;
import net.sf.jsqlparser.test.TestException;
import org.assertj.core.api.Assertions;
Expand Down Expand Up @@ -1247,4 +1250,44 @@ void testUniqueIndexIssue1893() throws JSQLParserException {
// A plain INDEX must still parse unchanged.
assertSqlCanBeParsedAndDeparsed("CREATE TABLE t (a int, INDEX idx (a))", true);
}

@Test
void testMySqlConstraintSymbolAndIndexNameIssue1570() throws JSQLParserException {
String uniqueSql = "CREATE TABLE table1 (col1 INT, col2 INT UNIQUE, "
+ "CONSTRAINT my_constraint UNIQUE KEY index_name (col1))";
CreateTable uniqueTable = (CreateTable) assertSqlCanBeParsedAndDeparsed(uniqueSql, true);
NamedConstraint unique = (NamedConstraint) uniqueTable.getIndexes().get(0);

assertEquals("my_constraint", unique.getName());
assertEquals("index_name", unique.getIndexName());
assertEquals("UNIQUE KEY", unique.getType());

String foreignKeySql = "CREATE TABLE table2 (id INT, parent_id INT, "
+ "CONSTRAINT fk_parent FOREIGN KEY fk_parent_idx (parent_id) "
+ "REFERENCES parent (id))";
CreateTable foreignKeyTable =
(CreateTable) assertSqlCanBeParsedAndDeparsed(foreignKeySql, true);
ForeignKeyIndex foreignKey = (ForeignKeyIndex) foreignKeyTable.getIndexes().get(0);

assertEquals("fk_parent", foreignKey.getName());
assertEquals("fk_parent_idx", foreignKey.getIndexName());
}

@Test
void testMySqlUnnamedConstraintAndUniqueIndexOptionsIssues1570And538()
throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed(
"CREATE TABLE table1 (col1 INT, CONSTRAINT UNIQUE KEY (col1))", true);

String sql = "CREATE TABLE g_platform_payway (id INT, platform_code VARCHAR (45), "
+ "pay_way VARCHAR (32), UNIQUE uniq_platform_payway USING BTREE "
+ "(platform_code, pay_way) COMMENT 'should be unique')";
CreateTable createTable = (CreateTable) assertSqlCanBeParsedAndDeparsed(sql, true);
NamedConstraint unique = (NamedConstraint) createTable.getIndexes().get(0);

assertNull(unique.getName());
assertEquals("uniq_platform_payway", unique.getIndexName());
assertEquals("BTREE", unique.getUsing());
assertEquals(List.of("COMMENT", "'should be unique'"), unique.getIndexSpec());
}
}
Loading