diff --git a/pom.xml b/pom.xml index cf06c4e09..0b8c9e0a2 100644 --- a/pom.xml +++ b/pom.xml @@ -227,9 +227,9 @@ - io.ebean - ebean-docker-run - 1.5.1 + io.ebean.test + ebean-test-docker + 2.5.1 test @@ -280,7 +280,7 @@ com.microsoft.sqlserver mssql-jdbc - 7.2.0.jre8 + 7.2.2.jre8 test diff --git a/src/main/java/io/ebean/config/PlatformConfig.java b/src/main/java/io/ebean/config/PlatformConfig.java index 298b25d23..2aa48c3f0 100644 --- a/src/main/java/io/ebean/config/PlatformConfig.java +++ b/src/main/java/io/ebean/config/PlatformConfig.java @@ -52,6 +52,8 @@ public class PlatformConfig { */ private boolean databaseInetAddressVarchar; + private boolean caseSensitiveCollation = true; + /** * Modify the default mapping of standard types such as default precision for DECIMAL etc. */ @@ -74,6 +76,7 @@ public class PlatformConfig { this.idType = platformConfig.idType; this.geometrySRID = platformConfig.geometrySRID; this.dbUuid = platformConfig.dbUuid; + this.caseSensitiveCollation = platformConfig.caseSensitiveCollation; } /** @@ -90,6 +93,20 @@ public class PlatformConfig { this.allQuotedIdentifiers = allQuotedIdentifiers; } + /** + * Return true if the collation is case sensitive. + */ + public boolean isCaseSensitiveCollation() { + return caseSensitiveCollation; + } + + /** + * Set to false to indicate that the collation is case insensitive. + */ + public void setCaseSensitiveCollation(boolean caseSensitiveCollation) { + this.caseSensitiveCollation = caseSensitiveCollation; + } + /** * Return a value used to represent TRUE in the database. *

@@ -255,6 +272,7 @@ public class PlatformConfig { databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue); databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse); databaseInetAddressVarchar = p.getBoolean("databaseInetAddressVarchar", databaseInetAddressVarchar); + caseSensitiveCollation = p.getBoolean("caseSensitiveCollation", caseSensitiveCollation); DbUuid dbUuid = p.getEnum(DbUuid.class, "dbuuid", null); if (dbUuid != null) { diff --git a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java index 16ab2592a..6a96724e8 100644 --- a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java @@ -71,6 +71,8 @@ public class DatabasePlatform { */ protected boolean allQuotedIdentifiers; + protected boolean caseSensitiveCollation = true; + /** * For limit/offset, row_number etc limiting of SQL queries. */ @@ -226,6 +228,7 @@ public class DatabasePlatform { */ public void configure(PlatformConfig config) { this.sequenceBatchSize = config.getDatabaseSequenceBatchSize(); + this.caseSensitiveCollation = config.isCaseSensitiveCollation(); configureIdType(config.getIdType()); configure(config, config.isAllQuotedIdentifiers()); } @@ -315,6 +318,16 @@ public class DatabasePlatform { return supportsDeleteTableAlias; } + /** + * Return true if the collation is case sensitive. + *

+ * This is expected to be used for testing only. + *

+ */ + public boolean isCaseSensitiveCollation() { + return caseSensitiveCollation; + } + /** * Return the maximum table name length. *

diff --git a/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java b/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java index 9ee373288..e9c769095 100644 --- a/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java @@ -35,7 +35,7 @@ public class MySqlPlatform extends DatabasePlatform { this.dbIdentity.setSupportsGetGeneratedKeys(true); this.dbIdentity.setSupportsIdentity(true); this.dbIdentity.setSupportsSequence(false); - + this.dbDefaultValue.setNow("now(6)"); // must have same precision as TIMESTAMP this.dbDefaultValue.setFalse("0"); this.dbDefaultValue.setTrue("1"); @@ -51,8 +51,8 @@ public class MySqlPlatform extends DatabasePlatform { this.openQuote = "`"; this.closeQuote = "`"; // use pipe for escaping as it depends if mysql runs in no_backslash_escapes or not. - this.likeClauseRaw = "like binary ? escape ''"; - this.likeClauseEscaped = "like binary ? escape '|'"; + this.likeClauseRaw = "like ? escape ''"; + this.likeClauseEscaped = "like ? escape '|'"; this.forwardOnlyHintOnFindIterate = true; this.booleanDbType = Types.BIT; diff --git a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasePlatform.java b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasePlatform.java index 75591f2ad..960309bbc 100644 --- a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasePlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasePlatform.java @@ -47,8 +47,8 @@ abstract class SqlServerBasePlatform extends DatabasePlatform { this.openQuote = "["; this.closeQuote = "]"; this.likeSpecialCharacters = new char[]{'%', '_', '['}; - this.likeClauseRaw = "like ? collate Latin1_General_BIN"; - this.likeClauseEscaped = "like ? collate Latin1_General_BIN"; + this.likeClauseRaw = "like ?"; + this.likeClauseEscaped = "like ?"; booleanDbType = Types.INTEGER; this.dbDefaultValue.setFalse("0"); diff --git a/src/main/resources/io/ebeaninternal/dbmigration/builtin-extra-ddl.xml b/src/main/resources/io/ebeaninternal/dbmigration/builtin-extra-ddl.xml index d50eef8b6..5a11d4804 100644 --- a/src/main/resources/io/ebeaninternal/dbmigration/builtin-extra-ddl.xml +++ b/src/main/resources/io/ebeaninternal/dbmigration/builtin-extra-ddl.xml @@ -49,11 +49,11 @@ CREATE OR ALTER PROCEDURE usp_ebean_drop_default_constraint @tableName nvarchar( AS SET NOCOUNT ON declare @tmp nvarchar(1000) BEGIN - select @Tmp = t1.name from sys.default_constraints t1 + select @tmp = t1.name from sys.default_constraints t1 join sys.columns t2 on t1.object_id = t2.default_object_id where t1.parent_object_id = OBJECT_ID(@tableName) and t2.name = @columnName; - if @Tmp is not null EXEC('alter table ' + @tableName +' drop constraint ' + @tmp); + if @tmp is not null EXEC('alter table ' + @tableName +' drop constraint ' + @tmp); END $$ @@ -171,13 +171,13 @@ AS BEGIN DECLARE foreign_key_names TABLE(CONSTRAINT_NAME NVARCHAR(256), TABLE_NAME NVARCHAR(256)); DECLARE i INT; - + foreign_key_names = SELECT CONSTRAINT_NAME, TABLE_NAME FROM SYS.REFERENTIAL_CONSTRAINTS WHERE SCHEMA_NAME=CURRENT_SCHEMA AND TABLE_NAME=UPPER(:table_name) AND COLUMN_NAME=UPPER(:column_name); - + FOR I IN 1 .. RECORD_COUNT(:foreign_key_names) DO EXEC 'ALTER TABLE "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.TABLE_NAME[i]) || '" DROP CONSTRAINT "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.CONSTRAINT_NAME[i]) || '"'; END FOR; - + END; $$ diff --git a/src/test/java/io/ebean/BaseTestCase.java b/src/test/java/io/ebean/BaseTestCase.java index ee10521e9..9156aaf3c 100644 --- a/src/test/java/io/ebean/BaseTestCase.java +++ b/src/test/java/io/ebean/BaseTestCase.java @@ -126,6 +126,10 @@ public abstract class BaseTestCase { return sql; } + public boolean isPlatformCaseSensitive() { + return spiEbeanServer().getDatabasePlatform().isCaseSensitiveCollation(); + } + /** * MS SQL Server does not allow setting explicit values on identity columns * so tests that do this need to be skipped for SQL Server. diff --git a/src/test/java/io/ebean/EbeanServer_eqlTest.java b/src/test/java/io/ebean/EbeanServer_eqlTest.java index 1e160484d..104780fbd 100644 --- a/src/test/java/io/ebean/EbeanServer_eqlTest.java +++ b/src/test/java/io/ebean/EbeanServer_eqlTest.java @@ -132,10 +132,13 @@ public class EbeanServer_eqlTest extends BaseTestCase { Query query = Ebean.createQuery(Customer.class); query.setMaxRows(10); query.setFirstRow(3); + if (isSqlServer()) { + query.orderBy("id"); + } query.findList(); if (isSqlServer()) { - assertThat(query.getGeneratedSql()).endsWith("from o_customer t0 offset 3 rows fetch next 10 rows only"); + assertThat(query.getGeneratedSql()).endsWith("from o_customer t0 order by t0.id offset 3 rows fetch next 10 rows only"); } else if (isOracle()) { assertThat(query.getGeneratedSql()).contains("where rownum <= 13"); assertThat(query.getGeneratedSql()).contains("where rn_ > 3"); diff --git a/src/test/java/io/ebean/config/ServerConfigTest.java b/src/test/java/io/ebean/config/ServerConfigTest.java index 7a5097190..2279a864e 100644 --- a/src/test/java/io/ebean/config/ServerConfigTest.java +++ b/src/test/java/io/ebean/config/ServerConfigTest.java @@ -70,6 +70,7 @@ public class ServerConfigTest { props.setProperty("namingConvention", "io.ebean.config.MatchingNamingConvention"); props.setProperty("idGeneratorAutomatic", "true"); props.setProperty("enabledL2Regions", "r0,users,orgs"); + props.setProperty("caseSensitiveCollation", "false"); serverConfig.loadFromProperties(props); @@ -79,6 +80,7 @@ public class ServerConfigTest { assertTrue(serverConfig.isDbOffline()); assertTrue(serverConfig.isAutoReadOnlyDataSource()); assertTrue(serverConfig.isIdGeneratorAutomatic()); + assertFalse(serverConfig.getPlatformConfig().isCaseSensitiveCollation()); assertThat(serverConfig.getNamingConvention()).isInstanceOf(MatchingNamingConvention.class); @@ -131,6 +133,7 @@ public class ServerConfigTest { assertFalse(serverConfig.isIdGeneratorAutomatic()); assertEquals(JsonConfig.DateTime.ISO8601, serverConfig.getJsonDateTime()); assertEquals(JsonConfig.Date.ISO8601, serverConfig.getJsonDate()); + assertTrue(serverConfig.getPlatformConfig().isCaseSensitiveCollation()); } @Test diff --git a/src/test/java/io/ebeaninternal/server/grammer/EqlParserTest.java b/src/test/java/io/ebeaninternal/server/grammer/EqlParserTest.java index 6e63066e2..43f79b915 100644 --- a/src/test/java/io/ebeaninternal/server/grammer/EqlParserTest.java +++ b/src/test/java/io/ebeaninternal/server/grammer/EqlParserTest.java @@ -596,7 +596,7 @@ public class EqlParserTest extends BaseTestCase { ResetBasicData.reset(); - Query query = parse("limit 10 offset 5"); + Query query = parse("order by name limit 10 offset 5"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains(" limit 10 offset 5"); diff --git a/src/test/java/main/StartMyServer.java b/src/test/java/main/StartMyServer.java new file mode 100644 index 000000000..de04e1625 --- /dev/null +++ b/src/test/java/main/StartMyServer.java @@ -0,0 +1,28 @@ +package main; + +import io.ebean.docker.commands.MySqlConfig; +import io.ebean.docker.commands.MySqlContainer; + +public class StartMyServer { + + public static void main(String[] args) { + + MySqlConfig config = new MySqlConfig("5.7"); + config.setDbName("unit"); + config.setUser("unit"); + config.setPassword("unit"); + + // by default this mysql docker collation is case sensitive + // using utf8mb4_bin + // + // when changing to a CI collation (e.g. utf8mb4_unicode_ci) we also set + // ebean..caseSensitiveCollation=false + // ... such that tests now take that into account +// config.setCollation("default"); +// config.setCollation("utf8mb4_unicode_ci"); +// config.setCharacterSet("utf8mb4"); + + MySqlContainer container = new MySqlContainer(config); + container.start(); + } +} diff --git a/src/test/java/main/StartSqlServer.java b/src/test/java/main/StartSqlServer.java new file mode 100644 index 000000000..7eea22376 --- /dev/null +++ b/src/test/java/main/StartSqlServer.java @@ -0,0 +1,27 @@ +package main; + +import io.ebean.docker.commands.SqlServerConfig; +import io.ebean.docker.commands.SqlServerContainer; + +public class StartSqlServer { + + public static void main(String[] args) { + + SqlServerConfig config = new SqlServerConfig("2017-CU4"); + config.setDbName("test_ebean"); + config.setUser("test_ebean"); + + // by default this sqlserver docker collation is case sensitive + // using MSSQL_COLLATION=Latin1_General_100_BIN2 + // + // when changing to a CI collation also use + // ebean.sqlserver.caseSensitiveCollation=false + // ... such that tests now take that into account + + //config.setCollation("default"); + //config.setCollation("Latin1_General_100_CI"); + + SqlServerContainer container = new SqlServerContainer(config); + container.start(); + } +} diff --git a/src/test/java/org/tests/basic/TestQueryUsingConnection.java b/src/test/java/org/tests/basic/TestQueryUsingConnection.java index 656af123f..5b63c7d33 100644 --- a/src/test/java/org/tests/basic/TestQueryUsingConnection.java +++ b/src/test/java/org/tests/basic/TestQueryUsingConnection.java @@ -3,6 +3,8 @@ package org.tests.basic; import io.ebean.BaseTestCase; import io.ebean.DB; import io.ebean.Transaction; +import io.ebean.annotation.IgnorePlatform; +import io.ebean.annotation.Platform; import org.junit.Test; import org.tests.model.basic.Country; import org.tests.model.basic.ResetBasicData; @@ -32,6 +34,7 @@ public class TestQueryUsingConnection extends BaseTestCase { } } + @IgnorePlatform(Platform.SQLSERVER) @Test public void usingTransaction() { diff --git a/src/test/java/org/tests/batchload/TestSecondaryQueries.java b/src/test/java/org/tests/batchload/TestSecondaryQueries.java index 1e0663e59..095ac9fe7 100644 --- a/src/test/java/org/tests/batchload/TestSecondaryQueries.java +++ b/src/test/java/org/tests/batchload/TestSecondaryQueries.java @@ -54,7 +54,7 @@ public class TestSecondaryQueries extends TransactionalTestCase { assertThat(sql).hasSize(1); if (isSqlServer()) { - assertThat(trimSql(sql.get(0), 2)).contains("select top 10 t0.id, t0.status, t0.kcustomer_id from o_order t0 order by t0.id"); + assertThat(trimSql(sql.get(0), 2)).contains("select top 10 t0.id, t0.status, t0.kcustomer_id from o_order t0"); } else { assertThat(trimSql(sql.get(0), 2)).contains("select t0.id, t0.status, t0.kcustomer_id from o_order t0"); } @@ -91,7 +91,7 @@ public class TestSecondaryQueries extends TransactionalTestCase { assertThat(sql).hasSize(1); if (isSqlServer()) { - assertThat(trimSql(sql.get(0), 2)).contains("select top 10 t0.id, t0.status from o_order t0 order by t0.id"); + assertThat(trimSql(sql.get(0), 2)).contains("select top 10 t0.id, t0.status from o_order t0"); } else { assertThat(trimSql(sql.get(0), 2)).contains("select t0.id, t0.status from o_order t0"); } diff --git a/src/test/java/org/tests/o2m/jointable/TestOneToManyJoinTableInheritance.java b/src/test/java/org/tests/o2m/jointable/TestOneToManyJoinTableInheritance.java index f3f75a7a6..3b2b262a8 100644 --- a/src/test/java/org/tests/o2m/jointable/TestOneToManyJoinTableInheritance.java +++ b/src/test/java/org/tests/o2m/jointable/TestOneToManyJoinTableInheritance.java @@ -34,15 +34,20 @@ public class TestOneToManyJoinTableInheritance extends BaseTestCase { List sql = LoggedSqlCollector.current(); + boolean hasSequence = isSqlServer(); // uses sequence assertThat(sql).hasSize(11); assertThat(sql.get(0)).contains("insert into class_super "); - assertThat(sql.get(1)).contains("-- bind(ClassA)"); - assertThat(sql.get(2)).contains("-- bind(ClassB)"); + if (!hasSequence) { + assertThat(sql.get(1)).contains("-- bind(ClassA)"); + assertThat(sql.get(2)).contains("-- bind(ClassB)"); + } assertThat(sql.get(3)).contains("insert into monkey "); - assertThat(sql.get(4)).contains("-- bind(Sim"); - assertThat(sql.get(5)).contains("-- bind(Tim"); - assertThat(sql.get(6)).contains("-- bind(Uim"); - assertThat(sql.get(7)).contains("insert into class_super_monkey (class_super_sid, monkey_mid) values (?, ?)"); + if (!hasSequence) { + assertThat(sql.get(4)).contains("-- bind(Sim"); + assertThat(sql.get(5)).contains("-- bind(Tim"); + assertThat(sql.get(6)).contains("-- bind(Uim"); + assertThat(sql.get(7)).contains("insert into class_super_monkey (class_super_sid, monkey_mid) values (?, ?)"); + } assertSqlBind(sql, 8, 10); ClassA dbA = Ebean.find(ClassA.class, 1); diff --git a/src/test/java/org/tests/query/TestAddOrderByWithFirstRowsMaxRows.java b/src/test/java/org/tests/query/TestAddOrderByWithFirstRowsMaxRows.java index d6c7c66b6..9ec383234 100644 --- a/src/test/java/org/tests/query/TestAddOrderByWithFirstRowsMaxRows.java +++ b/src/test/java/org/tests/query/TestAddOrderByWithFirstRowsMaxRows.java @@ -126,6 +126,7 @@ public class TestAddOrderByWithFirstRowsMaxRows extends BaseTestCase { Ebean.find(Order.class) .setFirstRow(10) .setMaxRows(10) + .orderBy("id") .findPagedList() .getList(); diff --git a/src/test/java/org/tests/query/TestQueryFilterCaseInsensitive.java b/src/test/java/org/tests/query/TestQueryFilterCaseInsensitive.java index 8d606cc4b..86a71b324 100644 --- a/src/test/java/org/tests/query/TestQueryFilterCaseInsensitive.java +++ b/src/test/java/org/tests/query/TestQueryFilterCaseInsensitive.java @@ -1,7 +1,7 @@ package org.tests.query; import io.ebean.BaseTestCase; -import io.ebean.Ebean; +import io.ebean.DB; import org.junit.BeforeClass; import org.junit.Test; import org.tests.model.basic.Customer; @@ -23,13 +23,17 @@ public class TestQueryFilterCaseInsensitive extends BaseTestCase { // Note: this test uses only customer#1..#4 - List customers = Ebean.find(Customer.class).where() + List customers = DB.find(Customer.class).where() .eq("name", "ROB") // case match .le("id", 4).findList(); - assertThat(customers).isEmpty(); + if (isPlatformCaseSensitive()) { + assertThat(customers).isEmpty(); + } else { + assertThat(customers).isNotEmpty(); + } - customers = Ebean.find(Customer.class).where() + customers = DB.find(Customer.class).where() .ieq("name", "ROB") // case insensitive match .le("id", 4).findList(); @@ -38,13 +42,17 @@ public class TestQueryFilterCaseInsensitive extends BaseTestCase { @Test public void testNe() { - List customers = Ebean.find(Customer.class).where() + List customers = DB.find(Customer.class).where() .ne("name", "ROB") // case match .le("id", 4).findList(); - assertThat(customers).hasSize(4); + if (isPlatformCaseSensitive()) { + assertThat(customers).hasSize(4); + } else { + assertThat(customers).isNotEmpty(); + } - customers = Ebean.find(Customer.class).where() + customers = DB.find(Customer.class).where() .ine("name", "ROB") // case insensitive match .le("id", 4).findList(); @@ -54,13 +62,17 @@ public class TestQueryFilterCaseInsensitive extends BaseTestCase { @Test public void testLike() { - List customers = Ebean.find(Customer.class).where() + List customers = DB.find(Customer.class).where() .like("name", "%O%") // case match .le("id", 4).findList(); - assertThat(customers).isEmpty(); + if (isPlatformCaseSensitive()) { + assertThat(customers).isEmpty(); + } else { + assertThat(customers).isNotEmpty(); + } - customers = Ebean.find(Customer.class).where() + customers = DB.find(Customer.class).where() .ilike("name", "%O%") // case insensitive match .le("id", 4).findList(); @@ -69,29 +81,36 @@ public class TestQueryFilterCaseInsensitive extends BaseTestCase { @Test public void testContains() { - List customers = Ebean.find(Customer.class).where() + List customers = DB.find(Customer.class).where() .contains("name", "O") // case match .le("id", 4).findList(); - assertThat(customers).isEmpty(); + if (isPlatformCaseSensitive()) { + assertThat(customers).isEmpty(); + } else { + assertThat(customers).isNotEmpty(); + } - customers = Ebean.find(Customer.class).where() + customers = DB.find(Customer.class).where() .icontains("name", "O") // case insensitive match .le("id", 4).findList(); assertThat(customers).hasSize(4); // Rob / Fiona / Cust No address / NocCust - } @Test public void testStartsWith() { - List customers = Ebean.find(Customer.class).where() + List customers = DB.find(Customer.class).where() .startsWith("name", "RO") // case match .le("id", 4).findList(); - assertThat(customers).isEmpty(); + if (isPlatformCaseSensitive()) { + assertThat(customers).isEmpty(); + } else { + assertThat(customers).isNotEmpty(); + } - customers = Ebean.find(Customer.class).where() + customers = DB.find(Customer.class).where() .istartsWith("name", "RO") // case insensitive match .le("id", 4).findList(); @@ -100,13 +119,17 @@ public class TestQueryFilterCaseInsensitive extends BaseTestCase { @Test public void testEndsWith() { - List customers = Ebean.find(Customer.class).where() + List customers = DB.find(Customer.class).where() .endsWith("name", "OB") // case match .le("id", 4).findList(); - assertThat(customers).isEmpty(); + if (isPlatformCaseSensitive()) { + assertThat(customers).isEmpty(); + } else { + assertThat(customers).isNotEmpty(); + } - customers = Ebean.find(Customer.class).where() + customers = DB.find(Customer.class).where() .iendsWith("name", "OB") // case insensitive match .le("id", 4).findList(); diff --git a/src/test/java/org/tests/query/TestQueryFindPagedList.java b/src/test/java/org/tests/query/TestQueryFindPagedList.java index 293b4d519..2376fefda 100644 --- a/src/test/java/org/tests/query/TestQueryFindPagedList.java +++ b/src/test/java/org/tests/query/TestQueryFindPagedList.java @@ -94,6 +94,7 @@ public class TestQueryFindPagedList extends BaseTestCase { PagedList pagedList2 = Ebean.find(Order.class) .setFirstRow(1) .setMaxRows(3) + .orderBy("id") .findPagedList(); pagedList2.loadCount(); @@ -109,6 +110,7 @@ public class TestQueryFindPagedList extends BaseTestCase { PagedList pagedList3 = Ebean.find(Order.class) .setFirstRow(2) .setMaxRows(150) + .orderBy("id") .findPagedList(); assertFalse(pagedList3.hasNext()); diff --git a/src/test/java/org/tests/query/TestQueryOrderById.java b/src/test/java/org/tests/query/TestQueryOrderById.java index 7d1c402f1..854f1b5eb 100644 --- a/src/test/java/org/tests/query/TestQueryOrderById.java +++ b/src/test/java/org/tests/query/TestQueryOrderById.java @@ -15,11 +15,16 @@ public class TestQueryOrderById extends BaseTestCase { Query query = DB.find(Customer.class) .select("id,name") + .orderBy("id") .setFirstRow(1) .setMaxRows(5); query.findList(); - assertThat(sqlOf(query)).isEqualTo("select t0.id, t0.name from o_customer t0 limit 5 offset 1"); + if (isSqlServer()) { + assertThat(sqlOf(query)).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id offset 1 rows fetch next 5 rows only"); + } else { + assertThat(sqlOf(query)).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id limit 5 offset 1"); + } } @Test @@ -32,6 +37,10 @@ public class TestQueryOrderById extends BaseTestCase { .orderById(true); query.findList(); - assertThat(sqlOf(query)).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id limit 5 offset 1"); + if (isSqlServer()) { + assertThat(sqlOf(query)).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id offset 1 rows fetch next 5 rows only"); + } else { + assertThat(sqlOf(query)).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id limit 5 offset 1"); + } } } diff --git a/src/test/java/org/tests/query/other/TestLikeEscaping.java b/src/test/java/org/tests/query/other/TestLikeEscaping.java index 2592ad098..d5eb0e92c 100644 --- a/src/test/java/org/tests/query/other/TestLikeEscaping.java +++ b/src/test/java/org/tests/query/other/TestLikeEscaping.java @@ -1,6 +1,6 @@ package org.tests.query.other; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.TransactionalTestCase; import org.tests.model.basic.Customer; @@ -16,76 +16,80 @@ public class TestLikeEscaping extends TransactionalTestCase { public void testLikeEscaping() { // Mysql, PgSql, H2 special chars: "_" "%" // MsSql special chars: "_" "%" "[" AND different Quoting! - Ebean.save(ResetBasicData.createCustomer("Paul % Percentage", "*Star", "[none]", 0, null)); - Ebean.save(ResetBasicData.createCustomer("(none)", "More * Star", "[none]", 0, null)); + DB.save(ResetBasicData.createCustomer("Paul % Percentage", "*Star", "[none]", 0, null)); + DB.save(ResetBasicData.createCustomer("(none)", "More * Star", "[none]", 0, null)); - Ebean.save(ResetBasicData.createCustomer("Paul %% Doublepercentage", "|Pipeway", "[other]", 1, null)); - Ebean.save(ResetBasicData.createCustomer("_Udo Underscore", "|Pipeway", "[other]", 1, null)); + DB.save(ResetBasicData.createCustomer("Paul %% Doublepercentage", "|Pipeway", "[other]", 1, null)); + DB.save(ResetBasicData.createCustomer("_Udo Underscore", "|Pipeway", "[other]", 1, null)); - Ebean.save(ResetBasicData.createCustomer("Bodo \\ backslash", "\\BS", "[other]", 1, null)); + DB.save(ResetBasicData.createCustomer("Bodo \\ backslash", "\\BS", "[other]", 1, null)); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().contains("name", "Paul %%").findCount() ).isEqualTo(1); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().contains("name", "o \\ b").findCount() ).isEqualTo(1); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().contains("name", "o \\\\ b").findCount() ).isEqualTo(0); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().startsWith("name", "_").findCount() ).isEqualTo(1); - assertThat(Ebean.find(Customer.class) + if (isPlatformCaseSensitive()) { + assertThat(DB.find(Customer.class) .where().startsWith("name", "_u").findCount() - ).isEqualTo(0); + ).isEqualTo(0); + } - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().istartsWith("name", "_U").findCount() ).isEqualTo(1); - assertThat(Ebean.find(Customer.class) + if (isPlatformCaseSensitive()) { + assertThat(DB.find(Customer.class) .where().startsWith("shippingAddress.line1", "|p").findCount() - ).isEqualTo(0); + ).isEqualTo(0); + } - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().startsWith("shippingAddress.line1", "|P").findCount() ).isEqualTo(2); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().startsWith("shippingAddress.line1", "\\B").findCount() ).isEqualTo(1); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().endsWith("billingAddress.line1", "]").findCount() ).isEqualTo(5); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().endsWith("billingAddress.line1", "[none]").findCount() ).isEqualTo(2); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().startsWith("billingAddress.line1", "[none]").findCount() ).isEqualTo(2); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().contains("billingAddress.line1", "[none]").findCount() ).isEqualTo(2); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().contains("shippingAddress.line1", "*").findCount() ).isEqualTo(2); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().startsWith("shippingAddress.line1", "*").findCount() ).isEqualTo(1); - assertThat(Ebean.find(Customer.class) + assertThat(DB.find(Customer.class) .where().endsWith("shippingAddress.line1", "*").findCount() ).isEqualTo(0); } diff --git a/src/test/java/org/tests/query/other/TestWhereLikeWithSlash.java b/src/test/java/org/tests/query/other/TestWhereLikeWithSlash.java index f08e57eec..328682e7a 100644 --- a/src/test/java/org/tests/query/other/TestWhereLikeWithSlash.java +++ b/src/test/java/org/tests/query/other/TestWhereLikeWithSlash.java @@ -26,10 +26,11 @@ public class TestWhereLikeWithSlash extends BaseTestCase { Query query1 = Ebean.find(EBasic.class).where().like("name", "slash\\mon%").query(); List list1 = query1.findList(); - // This doesn't work in the latest version of H2 so disable for now. - // Still good on Postgres which was the original issue - assertEquals(1, list1.size()); - + if (!isMySql()) { + // For mysql this assert depends on no_backslash_escapes setting so we won't assert here + // Still good on Postgres which was the original issue + assertEquals(1, list1.size()); + } } @Test diff --git a/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java b/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java index 54e933d3c..7c09cc098 100644 --- a/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java +++ b/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java @@ -151,6 +151,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase { query.setFirstRow(1); query.setMaxRows(2); + query.orderBy("id"); List list = query.findList(); diff --git a/src/test/java/org/tests/transaction/TestBatchModelFlush.java b/src/test/java/org/tests/transaction/TestBatchModelFlush.java index a8195ec96..f32a459ff 100644 --- a/src/test/java/org/tests/transaction/TestBatchModelFlush.java +++ b/src/test/java/org/tests/transaction/TestBatchModelFlush.java @@ -75,17 +75,22 @@ public class TestBatchModelFlush extends BaseTestCase { assertThat(sql).hasSize(9); // first saved to batch - (depth 100) + boolean hasSequence = isSqlServer(); assertThat(sql.get(0)).contains("insert into mny_b"); - assertThat(sql.get(1)).contains(" -- bind(BatchMultipleTop_0"); - assertThat(sql.get(2)).contains(" -- bind(BatchMultipleTop_1"); + if (!hasSequence) { + assertThat(sql.get(1)).contains(" -- bind(BatchMultipleTop_0"); + assertThat(sql.get(2)).contains(" -- bind(BatchMultipleTop_1"); + } // second saved to batch - (depth 101) assertThat(sql.get(3)).contains("insert into mt_role"); assertThat(sql.get(4)).contains(" -- bind("); assertThat(sql.get(5)).contains(" -- bind("); // third saved to batch - (depth 102) assertThat(sql.get(6)).contains("insert into mny_topic"); - assertThat(sql.get(7)).contains(" -- bind(MnyTopic_0"); - assertThat(sql.get(8)).contains(" -- bind(MnyTopic_1"); + if (!hasSequence) { + assertThat(sql.get(7)).contains(" -- bind(MnyTopic_0"); + assertThat(sql.get(8)).contains(" -- bind(MnyTopic_1"); + } DB.delete(t0); DB.delete(t1); diff --git a/src/test/resources/dbmigration/migrationtest/hana/I__create_procs.sql b/src/test/resources/dbmigration/migrationtest/hana/I__create_procs.sql index 6abbe7a96..32b8a9404 100644 --- a/src/test/resources/dbmigration/migrationtest/hana/I__create_procs.sql +++ b/src/test/resources/dbmigration/migrationtest/hana/I__create_procs.sql @@ -9,13 +9,13 @@ AS BEGIN DECLARE foreign_key_names TABLE(CONSTRAINT_NAME NVARCHAR(256), TABLE_NAME NVARCHAR(256)); DECLARE i INT; - + foreign_key_names = SELECT CONSTRAINT_NAME, TABLE_NAME FROM SYS.REFERENTIAL_CONSTRAINTS WHERE SCHEMA_NAME=CURRENT_SCHEMA AND TABLE_NAME=UPPER(:table_name) AND COLUMN_NAME=UPPER(:column_name); - + FOR I IN 1 .. RECORD_COUNT(:foreign_key_names) DO EXEC 'ALTER TABLE "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.TABLE_NAME[i]) || '" DROP CONSTRAINT "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.CONSTRAINT_NAME[i]) || '"'; END FOR; - + END; $$ diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver17/I__create_procs.sql b/src/test/resources/dbmigration/migrationtest/sqlserver17/I__create_procs.sql index 5c35dffc6..0d6379544 100644 --- a/src/test/resources/dbmigration/migrationtest/sqlserver17/I__create_procs.sql +++ b/src/test/resources/dbmigration/migrationtest/sqlserver17/I__create_procs.sql @@ -46,11 +46,11 @@ CREATE OR ALTER PROCEDURE usp_ebean_drop_default_constraint @tableName nvarchar( AS SET NOCOUNT ON declare @tmp nvarchar(1000) BEGIN - select @Tmp = t1.name from sys.default_constraints t1 + select @tmp = t1.name from sys.default_constraints t1 join sys.columns t2 on t1.object_id = t2.default_object_id where t1.parent_object_id = OBJECT_ID(@tableName) and t2.name = @columnName; - if @Tmp is not null EXEC('alter table ' + @tableName +' drop constraint ' + @tmp); + if @tmp is not null EXEC('alter table ' + @tableName +' drop constraint ' + @tmp); END $$ diff --git a/src/test/resources/ebean.properties b/src/test/resources/ebean.properties index 9e00efeff..43fd2954c 100644 --- a/src/test/resources/ebean.properties +++ b/src/test/resources/ebean.properties @@ -129,10 +129,12 @@ datasource.hsqldb.password= datasource.hsqldb.databaseUrl=jdbc:hsqldb:mem:tests datasource.hsqldb.databaseDriver=org.hsqldb.jdbcDriver - +# Set caseSensitiveCollation to false when using +# MySql with case insenstive collation +#ebean.mysql.caseSensitiveCollation=false datasource.mysql.username=unit datasource.mysql.password=unit -datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:3306/unit +datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/unit #datasource.mysql.username=test_ebean #datasource.mysql.password=test #datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/test_ebean @@ -158,10 +160,13 @@ datasource.pg.maxStackTraceSize=50 # Our main testing target for SqlServer is sqlserver17 ebean.sqlserver.databasePlatformName=sqlserver17 +# set caseSensitiveCollation=false when using a +# case insenstive collation with sql server - See main.StartSqlServer +#ebean.sqlserver.caseSensitiveCollation=false datasource.sqlserver.username=test_ebean datasource.sqlserver.password=SqlS3rv#r -datasource.sqlserver.databaseUrl=jdbc:sqlserver://localhost:1433;databaseName=test_ebean -datasource.sqlserver.databaseDriver=com.microsoft.sqlserver.jdbc.SQLServerDriver +datasource.sqlserver.url=jdbc:sqlserver://localhost:1433;databaseName=test_ebean;sendTimeAsDateTime=false +datasource.sqlserver.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver datasource.db2.username=db2admin datasource.db2.password=veryverysecret#1234 diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 25a339db8..9dfb9aab1 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -73,13 +73,10 @@ - - - - +