ADD: Support for quoted identifiers

This commit is contained in:
Roland Praml
2022-03-21 13:34:29 +01:00
parent 7e3fbbba62
commit 4077d906d1
10 changed files with 70 additions and 61 deletions
@@ -58,30 +58,16 @@ public class DbConstraintNormalise {
/**
* Trim off the platform quoted identifier quotes like [ ' and ".
*/
public boolean notQuoted(String tableName) {
public String trimQuotes(String identifier) {
// remove quoted identifier characters
for (String quotedIdentifier : quotedIdentifiers) {
if (tableName.contains(quotedIdentifier)) {
return false;
}
}
return true;
}
/**
* Trim off the platform quoted identifier quotes like [ ' and ".
*/
public String trimQuotes(String tableName) {
if (tableName == null) {
if (identifier == null) {
return "";
}
// remove quoted identifier characters
for (String quotedIdentifier : quotedIdentifiers) {
tableName = tableName.replace(quotedIdentifier, "");
identifier = identifier.replace(quotedIdentifier, "");
}
return tableName;
return identifier;
}
@@ -165,7 +165,7 @@ public class DatabasePlatform {
* want to use quoted identifiers for. The backticks get converted to the
* appropriate characters in convertQuotedIdentifiers
*/
private static final char BACK_TICK = '`';
private static final char[] QUOTED_IDENTIFIERS = new char[] { '"', '\'', '[', ']', '`' };
/**
* The non-escaped like clause (to stop slash being escaped on some platforms).
@@ -662,8 +662,8 @@ public class DatabasePlatform {
public String convertQuotedIdentifiers(String dbName) {
// Ignore null values e.g. schema name or catalog
if (dbName != null && !dbName.isEmpty()) {
if (dbName.charAt(0) == BACK_TICK) {
if (dbName.charAt(dbName.length() - 1) == BACK_TICK) {
if (isQuote(dbName.charAt(0))) {
if (isQuote(dbName.charAt(dbName.length() - 1))) {
return openQuote + dbName.substring(1, dbName.length() - 1) + closeQuote;
} else {
log.error("Missing backquote on [" + dbName + "]");
@@ -675,6 +675,15 @@ public class DatabasePlatform {
return dbName;
}
private boolean isQuote(char ch) {
for (char identifer : QUOTED_IDENTIFIERS) {
if (identifer == ch) {
return true;
}
}
return false;
}
/**
* Remove quoted identifier quotes from the table or column name if present.
*/
@@ -200,10 +200,10 @@ public abstract class AbstractHanaDdl extends PlatformDdl {
/**
* Joins alter table commands and add open/closing brackets for the alter statements
*/
private static class HanaAlterTableWrite extends BaseAlterTableWrite {
class HanaAlterTableWrite extends BaseAlterTableWrite {
public HanaAlterTableWrite(String tableName) {
super(tableName);
super(tableName, AbstractHanaDdl.this);
}
@Override
@@ -17,6 +17,8 @@ public class BaseAlterTableWrite implements DdlAlterTable {
protected static final String RAW_OPERATION = "$RAW";
protected final PlatformDdl platformDdl;
public class AlterCmd {
// the command (e.g. "alter", "modify"
private final String operation;
@@ -58,9 +60,9 @@ public class BaseAlterTableWrite implements DdlAlterTable {
// of all alter commands
target.append(getAlternation());
} else {
target.append("alter table ").append(tableName).append(' ').append(operation);
target.append("alter table ").append(platformDdl.quote(tableName)).append(' ').append(operation);
if (column != null) {
target.append(' ').append(column);
target.append(' ').append(platformDdl.quote(column));
}
if (!getAlternation().isEmpty()) {
target.append(' ').append(getAlternation());
@@ -85,8 +87,9 @@ public class BaseAlterTableWrite implements DdlAlterTable {
private boolean historyHandled;
public BaseAlterTableWrite(String tableName) {
public BaseAlterTableWrite(String tableName, PlatformDdl platformDdl) {
this.tableName = tableName;
this.platformDdl = platformDdl;
}
public String tableName() {
@@ -222,7 +222,7 @@ public class BaseTableDdl implements TableDdl {
String partitionMode = createTable.getPartitionMode();
DdlBuffer apply = writer.apply();
apply.append(platformDdl.getCreateTableCommandPrefix()).append(" ").append(tableName).append(" (");
apply.append(platformDdl.getCreateTableCommandPrefix()).append(" ").append(platformDdl.quote(tableName)).append(" (");
writeTableColumns(apply, columns, identity);
writeUniqueConstraints(apply, createTable);
writeCompoundUniqueConstraints(apply, createTable);
@@ -423,7 +423,7 @@ public class BaseTableDdl implements TableDdl {
if (i > 0) {
buffer.append(",");
}
buffer.append(columns[i].trim());
buffer.append(platformDdl.quote(columns[i].trim()));
}
buffer.append(")");
}
@@ -490,7 +490,7 @@ public class BaseTableDdl implements TableDdl {
buffer.append(",").newLine();
buffer.append(" constraint ").append(uqName).append(" unique ");
buffer.append("(");
buffer.append(column.getName());
buffer.append(platformDdl.quote(column.getName()));
buffer.append(")");
}
@@ -161,10 +161,10 @@ public class DB2Ddl extends PlatformDdl {
return writer.applyAlterTable(tableName, Db2AlterTableWrite::new);
};
static class Db2AlterTableWrite extends BaseAlterTableWrite {
class Db2AlterTableWrite extends BaseAlterTableWrite {
public Db2AlterTableWrite(String tableName) {
super(tableName);
super(tableName, DB2Ddl.this);
}
@Override
@@ -32,13 +32,14 @@ public class MySqlDdl extends PlatformDdl {
*/
@Override
public String dropIndex(String indexName, String tableName, boolean concurrent) {
return "drop index " + maxConstraintName(indexName) + " on " + tableName;
return "drop index " + maxConstraintName(indexName) + " on " + quote(tableName);
}
@Override
public void alterTableDropColumn(DdlWrite writer, String tableName, String columnName) {
if (this.useMigrationStoredProcedures) {
alterTable(writer, tableName).raw("CALL usp_ebean_drop_column('").append(tableName).append("', '").append(columnName).append("')");
alterTable(writer, tableName).raw("CALL usp_ebean_drop_column('").append(naming.normaliseTable(tableName))
.append("', '").append(naming.normaliseColumn(columnName)).append("')");
} else {
super.alterTableDropColumn(writer, tableName, columnName);
}
@@ -49,7 +50,7 @@ public class MySqlDdl extends PlatformDdl {
*/
@Override
public String alterTableDropForeignKey(String tableName, String fkName) {
return "alter table " + tableName + " drop foreign key " + maxConstraintName(fkName);
return "alter table " + quote(tableName) + " drop foreign key " + maxConstraintName(fkName);
}
@Override
@@ -146,7 +147,7 @@ public class MySqlDdl extends PlatformDdl {
if (DdlHelp.isDropComment(tableComment)) {
tableComment = "";
}
apply.append(String.format("alter table %s comment = '%s'", tableName, tableComment)).endOfStatement();
apply.append(String.format("alter table %s comment = '%s'", quote(tableName), tableComment)).endOfStatement();
}
@Override
@@ -258,7 +258,7 @@ public class PlatformDdl {
}
buffer.append(" ");
buffer.append(column.getName(), 29);
buffer.append(quote(column.getName()), 29);
buffer.append(columnDefn);
if (!Boolean.TRUE.equals(column.isPrimaryKey())) {
String defaultValue = convertDefaultValue(column.getDefaultValue());
@@ -278,7 +278,7 @@ public class PlatformDdl {
* Returns the check constraint.
*/
public String createCheckConstraint(String ckName, String checkConstraint) {
return " constraint " + ckName + " " + checkConstraint;
return " constraint " + maxConstraintName(ckName) + " " + checkConstraint;
}
/**
@@ -292,7 +292,7 @@ public class PlatformDdl {
* Return the drop foreign key clause.
*/
public String alterTableDropForeignKey(String tableName, String fkName) {
return "alter table " + alterTableIfExists + tableName + " " + dropConstraintIfExists + " " + maxConstraintName(fkName);
return "alter table " + alterTableIfExists + quote(tableName) + " " + dropConstraintIfExists + " " + maxConstraintName(fkName);
}
/**
@@ -372,7 +372,7 @@ public class PlatformDdl {
*/
public String createSequence(String sequenceName, DdlIdentity identity) {
StringBuilder sb = new StringBuilder("create sequence ");
sb.append(sequenceName);
sb.append(quote(sequenceName));
sb.append(identity.sequenceOptions(sequenceStartWith, sequenceIncrementBy, sequenceCache));
sb.append(";");
return sb.toString();
@@ -382,14 +382,14 @@ public class PlatformDdl {
* Return the drop sequence statement (potentially with if exists clause).
*/
public String dropSequence(String sequenceName) {
return dropSequenceIfExists + sequenceName;
return dropSequenceIfExists + quote(sequenceName);
}
/**
* Return the drop table statement (potentially with if exists clause).
*/
public String dropTable(String tableName) {
return dropTableIfExists + tableName + dropTableCascade;
return dropTableIfExists + quote(tableName) + dropTableCascade;
}
/**
@@ -422,7 +422,7 @@ public class PlatformDdl {
if (create.isNotExistsCheck()) {
buffer.append(createIndexIfNotExists);
}
buffer.append(maxConstraintName(create.getIndexName())).append(" on ").append(create.getTableName());
buffer.append(maxConstraintName(create.getIndexName())).append(" on ").append(quote(create.getTableName()));
appendColumns(create.getColumns(), buffer);
return buffer.toString();
}
@@ -435,7 +435,7 @@ public class PlatformDdl {
StringBuilder buffer = new StringBuilder(90);
buffer.append("foreign key");
appendColumns(request.cols(), buffer);
buffer.append(" references ").append(request.refTable());
buffer.append(" references ").append(quote(request.refTable()));
appendColumns(request.refCols(), buffer);
appendForeignKeySuffix(request, buffer);
return buffer.toString();
@@ -448,13 +448,13 @@ public class PlatformDdl {
StringBuilder buffer = new StringBuilder(90);
buffer
.append("alter table ").append(request.table())
.append("alter table ").append(quote(request.table()))
.append(" add constraint ").append(maxConstraintName(request.fkName()))
.append(" foreign key");
appendColumns(request.cols(), buffer);
buffer
.append(" references ")
.append(request.refTable());
.append(quote(request.refTable()));
appendColumns(request.refCols(), buffer);
appendForeignKeySuffix(request, buffer);
if (options.isForeignKeySkipCheck()) {
@@ -503,14 +503,14 @@ public class PlatformDdl {
* Drop a unique constraint from the table (Sometimes this is an index).
*/
public String alterTableDropUniqueConstraint(String tableName, String uniqueConstraintName) {
return "alter table " + tableName + " " + dropUniqueConstraint + " " + maxConstraintName(uniqueConstraintName);
return "alter table " + quote(tableName) + " " + dropUniqueConstraint + " " + maxConstraintName(uniqueConstraintName);
}
/**
* Drop a unique constraint from the table.
*/
public String alterTableDropConstraint(String tableName, String constraintName) {
return "alter table " + tableName + " " + dropConstraintIfExists + " " + maxConstraintName(constraintName);
return "alter table " + quote(tableName) + " " + dropConstraintIfExists + " " + maxConstraintName(constraintName);
}
/**
@@ -521,7 +521,7 @@ public class PlatformDdl {
public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, String[] nullableColumns) {
StringBuilder buffer = new StringBuilder(90);
buffer.append("alter table ").append(tableName).append(" add constraint ").append(maxConstraintName(uqName)).append(" unique ");
buffer.append("alter table ").append(quote(tableName)).append(" add constraint ").append(maxConstraintName(uqName)).append(" unique ");
appendColumns(columns, buffer);
return buffer.toString();
}
@@ -612,7 +612,7 @@ public class PlatformDdl {
* Alter table adding the check constraint.
*/
public String alterTableAddCheckConstraint(String tableName, String checkConstraintName, String checkConstraint) {
return "alter table " + tableName + " " + addConstraint + " " + maxConstraintName(checkConstraintName) + " " + checkConstraint;
return "alter table " + quote(tableName) + " " + addConstraint + " " + maxConstraintName(checkConstraintName) + " " + checkConstraint;
}
/**
@@ -656,7 +656,7 @@ public class PlatformDdl {
* Creates or replace a new DdlAlterTable for given tableName.
*/
protected DdlAlterTable alterTable(DdlWrite writer, String tableName) {
return writer.applyAlterTable(tableName, BaseAlterTableWrite::new);
return writer.applyAlterTable(tableName, k -> new BaseAlterTableWrite(k, this));
}
protected void appendColumns(String[] columns, StringBuilder buffer) {
@@ -665,7 +665,7 @@ public class PlatformDdl {
if (i > 0) {
buffer.append(",");
}
buffer.append(columns[i].trim());
buffer.append(quote(columns[i].trim()));
}
buffer.append(")");
}
@@ -713,7 +713,7 @@ public class PlatformDdl {
if (DdlHelp.isDropComment(tableComment)) {
tableComment = "";
}
apply.append(String.format("comment on table %s is '%s'", tableName, tableComment)).endOfStatement();
apply.append(String.format("comment on table %s is '%s'", quote(tableName), tableComment)).endOfStatement();
}
/**
@@ -723,7 +723,7 @@ public class PlatformDdl {
if (DdlHelp.isDropComment(comment)) {
comment = "";
}
apply.append(String.format("comment on column %s.%s is '%s'", table, column, comment)).endOfStatement();
apply.append(String.format("comment on column %s.%s is '%s'", quote(table), quote(column), comment)).endOfStatement();
}
/**
@@ -777,4 +777,9 @@ public class PlatformDdl {
public void addTablePartition(DdlBuffer apply, String partitionMode, String partitionColumn) {
// only supported by postgres initially
}
protected String quote(String dbName) {
return platform.convertQuotedIdentifiers(dbName);
}
}
@@ -68,9 +68,9 @@ public class SQLiteDdl extends PlatformDdl {
return writer.applyAlterTable(tableName, SQLiteAlterTableWrite::new);
}
static class SQLiteAlterTableWrite extends BaseAlterTableWrite {
class SQLiteAlterTableWrite extends BaseAlterTableWrite {
public SQLiteAlterTableWrite(String tableName) {
super(tableName);
super(tableName, SQLiteDdl.this);
}
@Override
@@ -39,7 +39,7 @@ public class SqlServerHistoryDdl implements PlatformHistoryDdl {
private void enableSystemVersioning(DdlWrite writer, String baseTable) {
DdlBuffer apply = writer.applyPostAlter();
apply.append("alter table ").append(baseTable).newLine()
apply.append("alter table ").append(quote(baseTable)).newLine()
.append(" add ").append(systemPeriodStart).append(" datetime2 GENERATED ALWAYS AS ROW START NOT NULL DEFAULT SYSUTCDATETIME(),").newLine()
.append(" ").append(systemPeriodEnd).append(" datetime2 GENERATED ALWAYS AS ROW END NOT NULL DEFAULT '9999-12-31T23:59:59.9999999',").newLine()
.append("period for system_time (").append(systemPeriodStart).append(", ").append(systemPeriodEnd).append(")").endOfStatement();
@@ -48,7 +48,8 @@ public class SqlServerHistoryDdl implements PlatformHistoryDdl {
.append(historyTableWithSchema(baseTable)).append("))").endOfStatement();
DdlBuffer drop = writer.dropAll();
drop.append("IF OBJECT_ID('").append(baseTable).append("', 'U') IS NOT NULL alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement();
drop.append("IF OBJECT_ID('").append(quote(baseTable)).append("', 'U') IS NOT NULL alter table ")
.append(quote(baseTable)).append(" set (system_versioning = off)").endOfStatement();
drop.append("IF OBJECT_ID('").append(historyTableName(baseTable)).append("', 'U') IS NOT NULL drop table ")
.append(historyTableName(baseTable)).endOfStatement();
}
@@ -68,8 +69,8 @@ public class SqlServerHistoryDdl implements PlatformHistoryDdl {
// switch of versioning & period - must be done before altering
DdlBuffer apply = writer.apply();
apply.append("-- dropping history support for ").append(baseTable).endOfStatement();
apply.append("alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement();
apply.append("alter table ").append(baseTable).append(" drop period for system_time").endOfStatement();
apply.append("alter table ").append(quote(baseTable)).append(" set (system_versioning = off)").endOfStatement();
apply.append("alter table ").append(quote(baseTable)).append(" drop period for system_time").endOfStatement();
apply.end();
// now drop tables & columns, they will go to alter table/post alter buffers
platformDdl.alterTableDropColumn(writer, baseTable, systemPeriodStart);
@@ -90,15 +91,19 @@ public class SqlServerHistoryDdl implements PlatformHistoryDdl {
if (!alter.isHistoryHandled()) {
// SQL Server 2016 does not need triggers
DdlBuffer apply = writer.apply();
apply.append("-- alter table ").append(tableName).append(" set (system_versioning = off (history_table=")
apply.append("-- alter table ").append(quote(tableName)).append(" set (system_versioning = off (history_table=")
.append(historyTableWithSchema(tableName)).append("))").endOfStatement();
apply.append("-- history migration goes here").newLine();
apply.append("-- alter table ").append(tableName).append(" set (system_versioning = on (history_table=")
apply.append("-- alter table ").append(quote(tableName)).append(" set (system_versioning = on (history_table=")
.append(historyTableWithSchema(tableName)).append("))").endOfStatement();
}
alter.setHistoryHandled();
}
protected String quote(String baseTable) {
return platformDdl.quote(baseTable);
}
protected String normalise(String tableName) {
return constraintNaming.normaliseTable(tableName);
}