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
7 changes: 7 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/feature/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
import net.sf.jsqlparser.statement.analyze.Analyze;
import net.sf.jsqlparser.statement.comment.Comment;
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
import net.sf.jsqlparser.statement.create.function.CreateFunction;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.procedure.CreateProcedure;
Expand Down Expand Up @@ -475,6 +476,12 @@ public enum Feature {
*/
drop, dropTable, dropIndex, dropView, dropSchema, dropSequence, dropTableIfExists, dropIndexIfExists, dropViewIfExists, dropSchemaIfExists, dropSequenceIfExists,

/**
* SQL "CREATE DATABASE" statement is allowed
*
* @see CreateDatabase
*/
createDatabase,
/**
* SQL "CREATE SCHEMA" statement is allowed
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
import net.sf.jsqlparser.statement.analyze.Analyze;
import net.sf.jsqlparser.statement.comment.Comment;
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.policy.CreatePolicy;
import net.sf.jsqlparser.statement.create.schema.CreateSchema;
Expand Down Expand Up @@ -118,6 +119,12 @@ default void visit(CreateSchema createSchema) {
this.visit(createSchema, null);
}

<S> T visit(CreateDatabase createDatabase, S context);

default void visit(CreateDatabase createDatabase) {
this.visit(createDatabase, null);
}

<S> T visit(CreateTable createTable, S context);

default void visit(CreateTable createTable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
import net.sf.jsqlparser.statement.analyze.Analyze;
import net.sf.jsqlparser.statement.comment.Comment;
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.policy.CreatePolicy;
import net.sf.jsqlparser.statement.create.schema.CreateSchema;
Expand Down Expand Up @@ -261,6 +262,11 @@ public <S> T visit(CreateSchema createSchema, S context) {
return null;
}

@Override
public <S> T visit(CreateDatabase createDatabase, S context) {
return null;
}

@Override
public <S> T visit(CreateTable createTable, S context) {
return createTable.getTable().accept(fromItemVisitor, context);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*-
* #%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.create.database;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;

/**
* A {@code CREATE DATABASE} statement. Modelled after MySQL, where the statement takes an optional
* {@code IF NOT EXISTS} and vendor-specific options, which are captured verbatim.
*/
public class CreateDatabase implements Statement {

private String databaseName;
private boolean hasIfNotExists = false;
private List<String> databaseOptions = null;

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}

/**
* The name of the database.
*
* @return the database name
*/
public String getDatabaseName() {
return databaseName;
}

public CreateDatabase setDatabaseName(String databaseName) {
this.databaseName = databaseName;
return this;
}

public boolean hasIfNotExists() {
return hasIfNotExists;
}

public CreateDatabase setIfNotExists(boolean hasIfNotExists) {
this.hasIfNotExists = hasIfNotExists;
return this;
}

/**
* The vendor-specific options of the database, captured as raw tokens.
*
* @return the list of option tokens, {@code null} when no options were given
*/
public List<String> getDatabaseOptions() {
return databaseOptions;
}

public CreateDatabase setDatabaseOptions(List<String> databaseOptions) {
this.databaseOptions = databaseOptions;
return this;
}

public CreateDatabase withDatabaseName(String databaseName) {
return this.setDatabaseName(databaseName);
}

public CreateDatabase withIfNotExists(boolean hasIfNotExists) {
return this.setIfNotExists(hasIfNotExists);
}

public CreateDatabase withDatabaseOptions(List<String> databaseOptions) {
return this.setDatabaseOptions(databaseOptions);
}

public CreateDatabase addDatabaseOptions(String... databaseOptions) {
List<String> collection =
Optional.ofNullable(getDatabaseOptions()).orElseGet(ArrayList::new);
Collections.addAll(collection, databaseOptions);
return this.withDatabaseOptions(collection);
}

public CreateDatabase addDatabaseOptions(Collection<String> databaseOptions) {
List<String> collection =
Optional.ofNullable(getDatabaseOptions()).orElseGet(ArrayList::new);
collection.addAll(databaseOptions);
return this.withDatabaseOptions(collection);
}

@Override
public String toString() {
String sql = "CREATE DATABASE";
if (hasIfNotExists) {
sql += " IF NOT EXISTS";
}
if (databaseName != null) {
sql += " " + databaseName;
}
if (databaseOptions != null && !databaseOptions.isEmpty()) {
sql += " " + String.join(" ", databaseOptions);
}
return sql;
}
}
12 changes: 12 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
import net.sf.jsqlparser.statement.analyze.Analyze;
import net.sf.jsqlparser.statement.comment.Comment;
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.policy.CreatePolicy;
import net.sf.jsqlparser.statement.create.schema.CreateSchema;
Expand Down Expand Up @@ -1166,6 +1167,17 @@ public void visit(CreateSchema createSchema) {
StatementVisitor.super.visit(createSchema);
}

@Override
public <S> Void visit(CreateDatabase createDatabase, S context) {
throwUnsupported(createDatabase);
return null;
}

@Override
public void visit(CreateDatabase createDatabase) {
StatementVisitor.super.visit(createDatabase);
}

@Override
public <S> Void visit(CreateTable create, S context) {
visit(create.getTable(), null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
import net.sf.jsqlparser.statement.analyze.Analyze;
import net.sf.jsqlparser.statement.comment.Comment;
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.policy.CreatePolicy;
import net.sf.jsqlparser.statement.create.schema.CreateSchema;
Expand Down Expand Up @@ -431,6 +432,12 @@ public <S> StringBuilder visit(CreateSchema aThis, S context) {
return builder;
}

@Override
public <S> StringBuilder visit(CreateDatabase aThis, S context) {
builder.append(aThis.toString());
return builder;
}

@Override
public <S> StringBuilder visit(CreateSequence createSequence, S context) {
new CreateSequenceDeParser(builder).deParse(createSequence);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
import net.sf.jsqlparser.statement.analyze.Analyze;
import net.sf.jsqlparser.statement.comment.Comment;
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
import net.sf.jsqlparser.statement.create.function.CreateFunction;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.policy.CreatePolicy;
Expand Down Expand Up @@ -299,6 +300,13 @@ public <S> Void visit(CreateSchema aThis, S context) {
return null;
}

@Override
public <S> Void visit(CreateDatabase aThis, S context) {
validateFeatureAndName(Feature.createDatabase, NamedObject.database,
aThis.getDatabaseName());
return null;
}

@Override
public <S> Void visit(CreateSequence createSequence, S context) {
getValidator(CreateSequenceValidator.class).validate(createSequence);
Expand Down
19 changes: 19 additions & 0 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import net.sf.jsqlparser.statement.analyze.*;
import net.sf.jsqlparser.statement.alter.*;
import net.sf.jsqlparser.statement.alter.sequence.*;
import net.sf.jsqlparser.statement.comment.*;
import net.sf.jsqlparser.statement.create.database.*;
import net.sf.jsqlparser.statement.create.function.*;
import net.sf.jsqlparser.statement.create.index.*;
import net.sf.jsqlparser.statement.create.policy.*;
Expand Down Expand Up @@ -10820,6 +10821,22 @@ List<String> PathSpecification():
}
}

CreateDatabase CreateDatabase():
{
CreateDatabase createDatabase = new CreateDatabase();
String databaseName = null;
List<String> databaseOptions = null;
}
{
<K_DATABASE>
[ LOOKAHEAD(2) <K_IF> <K_NOT> <K_EXISTS> { createDatabase.setIfNotExists(true); } ]
databaseName = RelObjectName() { createDatabase.setDatabaseName(databaseName); }
[ databaseOptions = captureRest() { createDatabase.setDatabaseOptions(databaseOptions); } ]
{
return createDatabase;
}
}

/**
* Parses a single table-level constraint inside CREATE TABLE (...).
* Handles INDEX, PRIMARY KEY, UNIQUE, KEY, FOREIGN KEY, CHECK, EXCLUDE.
Expand Down Expand Up @@ -13267,6 +13284,8 @@ Statement Create():
|
statement = CreateSchema()
|
statement = CreateDatabase()
|
statement = CreateSequence()
|
statement = CreateSynonym(isUsingOrReplace)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*-
* #%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.create.database;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import static net.sf.jsqlparser.test.TestUtils.assertDeparse;
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Arrays;
import org.junit.jupiter.api.Test;

public class CreateDatabaseTest {

@Test
void testCreateDatabaseIssue2070() throws JSQLParserException {
String statement = "CREATE DATABASE USERS";
assertSqlCanBeParsedAndDeparsed(statement);
assertDeparse(new CreateDatabase().withDatabaseName("USERS"), statement);
}

@Test
void testCreateDatabaseIfNotExists() throws JSQLParserException {
String statement = "CREATE DATABASE IF NOT EXISTS mydb";
assertSqlCanBeParsedAndDeparsed(statement);
assertDeparse(new CreateDatabase().withDatabaseName("mydb").withIfNotExists(true),
statement);
}

@Test
void testCreateDatabaseQuotedName() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("CREATE DATABASE `my db`");
assertSqlCanBeParsedAndDeparsed("CREATE DATABASE \"my db\"");
}

@Test
void testCreateDatabaseWithOptions() throws JSQLParserException {
String statement =
"CREATE DATABASE IF NOT EXISTS mydb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
assertSqlCanBeParsedAndDeparsed(statement);

Statement parsed = CCJSqlParserUtil.parse(statement);
CreateDatabase createDatabase = assertInstanceOf(CreateDatabase.class, parsed);
assertEquals("mydb", createDatabase.getDatabaseName());
assertTrue(createDatabase.hasIfNotExists());
assertEquals(
Arrays.asList("DEFAULT", "CHARACTER", "SET", "utf8mb4", "COLLATE",
"utf8mb4_unicode_ci"),
createDatabase.getDatabaseOptions());
}

@Test
void testCreateDatabaseAST() throws JSQLParserException {
Statement statement = CCJSqlParserUtil.parse("CREATE DATABASE USERS");
CreateDatabase createDatabase = assertInstanceOf(CreateDatabase.class, statement);
assertEquals("USERS", createDatabase.getDatabaseName());
assertFalse(createDatabase.hasIfNotExists());

statement = CCJSqlParserUtil.parse("CREATE DATABASE IF NOT EXISTS mydb");
createDatabase = assertInstanceOf(CreateDatabase.class, statement);
assertEquals("mydb", createDatabase.getDatabaseName());
assertTrue(createDatabase.hasIfNotExists());
}
}
Loading