diff --git a/ebean-api/src/main/java/io/ebean/config/DbConstraintNormalise.java b/ebean-api/src/main/java/io/ebean/config/DbConstraintNormalise.java index 71b6f8aff..c8dd4da60 100644 --- a/ebean-api/src/main/java/io/ebean/config/DbConstraintNormalise.java +++ b/ebean-api/src/main/java/io/ebean/config/DbConstraintNormalise.java @@ -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; } diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java index 276151075..d73d760a6 100644 --- a/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java +++ b/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java @@ -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. */ diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java index 69d0d2816..58e071a5d 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java @@ -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 diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseAlterTableWrite.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseAlterTableWrite.java index bd777d5a5..1bdcfdc30 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseAlterTableWrite.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseAlterTableWrite.java @@ -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() { diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java index c3bc5f791..60b22552c 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java @@ -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(")"); } diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java index 874bcc88f..b8ad7ca2d 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java @@ -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 diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java index d8ec08128..987303b20 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java @@ -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 diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java index e27edd762..3141ca3fb 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java @@ -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); + } + } diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SQLiteDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SQLiteDdl.java index 50ce99d25..c24dcff45 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SQLiteDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SQLiteDdl.java @@ -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 diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerHistoryDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerHistoryDdl.java index e2faa5ace..06aeff157 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerHistoryDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerHistoryDdl.java @@ -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); }