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
2 changes: 2 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 @@ -580,6 +580,8 @@ public enum Feature {
*/
createSequence,
/** Publication and subscription definitions. */
createCollation, alterCollation,

createPublication, alterPublication, createSubscription, alterSubscription,
/**
* Structured type, domain and extension statements.
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.statement.create.collation.CreateCollation;
import net.sf.jsqlparser.statement.alter.AlterCollation;
import net.sf.jsqlparser.statement.alter.AlterPolicy;
import net.sf.jsqlparser.statement.drop.DropPolicy;
import net.sf.jsqlparser.statement.create.statistics.CreateStatistics;
Expand Down Expand Up @@ -733,4 +735,20 @@ default <S> T visit(AlterStatistics statement, S context) {
default void visit(AlterStatistics statement) {
visit(statement, null);
}

default <S> T visit(CreateCollation statement, S context) {
return null;
}

default void visit(CreateCollation statement) {
visit(statement, null);
}

default <S> T visit(AlterCollation statement, S context) {
return null;
}

default void visit(AlterCollation statement) {
visit(statement, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*-
* #%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.alter;

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

public class AlterCollation implements Statement {
public enum Action {
REFRESH_VERSION, RENAME, OWNER, SET_SCHEMA
}

private String name;
private Action action;
private String newName;
private String owner;
private String schemaName;

public String getName() {
return name;
}

public void setName(String value) {
name = value;
}

public Action getAction() {
return action;
}

public void setAction(Action value) {
action = value;
}

public String getNewName() {
return newName;
}

public void setNewName(String value) {
newName = value;
}

public String getOwner() {
return owner;
}

public void setOwner(String value) {
owner = value;
}

public String getSchemaName() {
return schemaName;
}

public void setSchemaName(String value) {
schemaName = value;
}

public StringBuilder appendTo(StringBuilder sql) {
sql.append("ALTER COLLATION ").append(name);
switch (action) {
case REFRESH_VERSION:
sql.append(" REFRESH VERSION");
break;
case RENAME:
sql.append(" RENAME TO ").append(newName);
break;
case OWNER:
sql.append(" OWNER TO ").append(owner);
break;
case SET_SCHEMA:
sql.append(" SET SCHEMA ").append(schemaName);
break;
default:
throw new IllegalStateException("Unknown collation action: " + action);
}
return sql;
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}

@Override
public <T, S> T accept(StatementVisitor<T> visitor, S context) {
return visitor.visit(this, context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*-
* #%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.collation;

import java.util.List;
import java.util.function.Consumer;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.create.table.Index;

/** PostgreSQL collation copy or parameter definition, with mutually exclusive forms. */
public class CreateCollation implements Statement {
private String name;
private boolean ifNotExists;
private String sourceCollation;
private List<Index.Option> options;

public String getName() {
return name;
}

public void setName(String value) {
name = value;
}

public boolean isIfNotExists() {
return ifNotExists;
}

public void setIfNotExists(boolean value) {
ifNotExists = value;
}

public String getSourceCollation() {
return sourceCollation;
}

public void setSourceCollation(String source) {
sourceCollation = source;
if (source != null) {
options = null;
}
}

public List<Index.Option> getOptions() {
return options;
}

public void setOptions(List<Index.Option> options) {
this.options = options;
if (options != null) {
sourceCollation = null;
}
}

public StringBuilder appendTo(StringBuilder sql, Consumer<Expression> printer) {
sql.append("CREATE COLLATION ");
if (isIfNotExists()) {
sql.append("IF NOT EXISTS ");
}
sql.append(getName());
if (sourceCollation != null) {
sql.append(" FROM ").append(sourceCollation);
} else {
sql.append(' ');
Index.Option.appendListTo(sql, options, printer);
}
return sql;
}

public void visitExpressions(Consumer<Expression> visitor) {
if (sourceCollation == null && options != null) {
options.stream().map(Index.Option::getValue).filter(java.util.Objects::nonNull)
.forEach(visitor);
}
}

@Override
public String toString() {
StringBuilder sql = new StringBuilder();
return appendTo(sql, sql::append).toString();
}

@Override
public <T, S> T accept(StatementVisitor<T> visitor, S context) {
return visitor.visit(this, context);
}
}
13 changes: 13 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package net.sf.jsqlparser.util;

import net.sf.jsqlparser.statement.create.collation.CreateCollation;
import net.sf.jsqlparser.statement.alter.AlterCollation;
import net.sf.jsqlparser.statement.alter.AlterPolicy;
import net.sf.jsqlparser.statement.drop.DropPolicy;
import net.sf.jsqlparser.statement.create.statistics.CreateStatistics;
Expand Down Expand Up @@ -2968,4 +2970,15 @@ public <S> Void visit(CreateStatistics statement, S context) {
public <S> Void visit(AlterStatistics statement, S context) {
return null;
}

@Override
public <S> Void visit(CreateCollation statement, S context) {
statement.visitExpressions(expression -> expression.accept(this, context));
return null;
}

@Override
public <S> Void visit(AlterCollation statement, S context) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package net.sf.jsqlparser.util.deparser;

import net.sf.jsqlparser.statement.create.collation.CreateCollation;
import net.sf.jsqlparser.statement.alter.AlterCollation;
import net.sf.jsqlparser.statement.alter.AlterPolicy;
import net.sf.jsqlparser.statement.drop.DropPolicy;
import net.sf.jsqlparser.statement.create.statistics.CreateStatistics;
Expand Down Expand Up @@ -853,4 +855,15 @@ public <S> StringBuilder visit(CreateStatistics statement, S context) {
public <S> StringBuilder visit(AlterStatistics statement, S context) {
return statement.appendTo(builder);
}

@Override
public <S> StringBuilder visit(CreateCollation statement, S context) {
return statement.appendTo(builder,
expression -> expression.accept(expressionDeParser, context));
}

@Override
public <S> StringBuilder visit(AlterCollation statement, S context) {
return statement.appendTo(builder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public class FeaturesAllowed implements FeatureSetValidation, ModifyableFeatureS
* all "CREATE" {@link Feature}'s
*/
public static final FeaturesAllowed CREATE = new FeaturesAllowed("CREATE", Feature.createIndex,
Feature.createCollation,
Feature.createSchema, Feature.createSequence, Feature.createTable,
Feature.createTableUnlogged,
Feature.createTableCreateOptionStrings, Feature.createTableTableOptionStrings,
Expand All @@ -113,6 +114,7 @@ public class FeaturesAllowed implements FeatureSetValidation, ModifyableFeatureS
*/
public static final FeaturesAllowed ALTER =
new FeaturesAllowed("ALTER", Feature.alterTable, Feature.alterSequence,
Feature.alterCollation,
Feature.alterView, Feature.alterIndex, Feature.alterSchema)
.unmodifyable();
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public enum PostgresqlVersion implements Version {

// https://www.postgresql.org/docs/current/sql-createsequence.html
Feature.createSequence,
Feature.createCollation, Feature.alterCollation,
Feature.createPublication, Feature.alterPublication,
Feature.createSubscription, Feature.alterSubscription,
Feature.createType, Feature.alterType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package net.sf.jsqlparser.util.validation.validator;

import net.sf.jsqlparser.statement.create.collation.CreateCollation;
import net.sf.jsqlparser.statement.alter.AlterCollation;
import net.sf.jsqlparser.statement.alter.schema.AlterSchema;
import net.sf.jsqlparser.statement.oracle.OracleBlock;
import net.sf.jsqlparser.statement.oracle.OracleAssignment;
Expand Down Expand Up @@ -1024,4 +1026,17 @@ public <S> Void visit(OracleNullStatement statement, S context) {
return null;
}


@Override
public <S> Void visit(CreateCollation statement, S context) {
validateFeature(Feature.createCollation);
statement.visitExpressions(this::validateOptionalExpression);
return null;
}

@Override
public <S> Void visit(AlterCollation statement, S context) {
validateFeature(Feature.alterCollation);
return null;
}
}
38 changes: 38 additions & 0 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import net.sf.jsqlparser.schema.*;
import net.sf.jsqlparser.statement.*;
import net.sf.jsqlparser.statement.analyze.*;
import net.sf.jsqlparser.statement.alter.*;
import net.sf.jsqlparser.statement.create.collation.CreateCollation;
import net.sf.jsqlparser.statement.alter.schema.AlterSchema;
import net.sf.jsqlparser.statement.alter.database.AlterDatabase;
import net.sf.jsqlparser.statement.alter.sequence.*;
Expand Down Expand Up @@ -18441,6 +18442,8 @@ Statement Alter():
(
<K_ALTER>
(
LOOKAHEAD({ isKeywordAhead("COLLATION") }) statement = AlterCollation()
|
LOOKAHEAD({ isKeywordAhead("STATISTICS") }) statement = AlterStatistics()
|
LOOKAHEAD(<K_POLICY>) statement = AlterPolicy()
Expand Down Expand Up @@ -19650,6 +19653,8 @@ Statement Create():
{
<K_CREATE> [ <K_OR> <K_REPLACE> { isUsingOrReplace = true; } ]
(
LOOKAHEAD({ isKeywordAhead("COLLATION") }) { requireDdlSyntax(!isUsingOrReplace, "CREATE COLLATION does not support OR REPLACE"); } statement = CreateCollation()
|
LOOKAHEAD({ isKeywordAhead("STATISTICS") }) statement = CreateStatistics()
|
LOOKAHEAD({ isPostgreSqlRoleAhead() }) statement = CreateRole()
Expand Down Expand Up @@ -20952,3 +20957,36 @@ AlterStatistics AlterStatistics():
statement.setStatistics(target.intValue()); } ) ) )
{ return statement; }
}

CreateCollation CreateCollation():
{
CreateCollation statement = new CreateCollation(); String name; List<Index.Option> options;
}
{
ContextualKeyword("COLLATION")
[ LOOKAHEAD(2) <K_IF> <K_NOT> <K_EXISTS> { statement.setIfNotExists(true); } ]
name=AccessQualifiedName() { statement.setName(name); }
( <K_FROM> name=AccessQualifiedName() { statement.setSourceCollation(name); }
| options=PostgreSqlOptions(true) {
for (Index.Option option : options) {
requireDdlSyntax(option.getValue() == null || option.isUseEquals(),
"Collation parameter values require an equals sign");
}
statement.setOptions(options);
} )
{ return statement; }
}

AlterCollation AlterCollation():
{ AlterCollation statement = new AlterCollation(); String name; }
{
ContextualKeyword("COLLATION") name=AccessQualifiedName() { statement.setName(name); }
( <K_REFRESH> <K_VERSION> { statement.setAction(AlterCollation.Action.REFRESH_VERSION); }
| <K_RENAME> <K_TO> name=RelObjectName()
{ statement.setAction(AlterCollation.Action.RENAME); statement.setNewName(name); }
| <K_SET> <K_SCHEMA> name=RelObjectName()
{ statement.setAction(AlterCollation.Action.SET_SCHEMA); statement.setSchemaName(name); }
| ContextualKeyword("OWNER") <K_TO> name=RelObjectName()
{ statement.setAction(AlterCollation.Action.OWNER); statement.setOwner(name); } )
{ return statement; }
}
Loading
Loading