diff --git a/pom.xml b/pom.xml
index c47919e2e..f56f99055 100644
--- a/pom.xml
+++ b/pom.xml
@@ -88,7 +88,7 @@
io.ebean
ebean-annotation
- 6.5
+ 6.7
diff --git a/src/main/java/io/ebean/config/dbplatform/RowNumberSqlLimiter.java b/src/main/java/io/ebean/config/dbplatform/RowNumberSqlLimiter.java
deleted file mode 100644
index 9f6b4ad19..000000000
--- a/src/main/java/io/ebean/config/dbplatform/RowNumberSqlLimiter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package io.ebean.config.dbplatform;
-
-/**
- * Adds the ROW_NUMBER() OVER function to a query.
- */
-public class RowNumberSqlLimiter implements SqlLimiter {
-
- /**
- * ROW_NUMBER() OVER (ORDER BY
- */
- private static final String ROW_NUMBER_OVER = "row_number() over (order by ";
-
- /**
- * ) as rn,
- */
- private static final String ROW_NUMBER_AS = ") as rn, ";
-
- private final String rowNumberWindowAlias;
-
- /**
- * Specify the name of the rowNumberWindowAlias.
- */
- public RowNumberSqlLimiter(String rowNumberWindowAlias) {
- this.rowNumberWindowAlias = rowNumberWindowAlias;
- }
-
- public RowNumberSqlLimiter() {
- this("as limitresult");
- }
-
- @Override
- public SqlLimitResponse limit(SqlLimitRequest request) {
-
- String dbSql = request.getDbSql();
-
- StringBuilder sb = new StringBuilder(60 + dbSql.length());
-
- int firstRow = request.getFirstRow();
-
- int lastRow = request.getMaxRows();
- if (lastRow > 0) {
- lastRow += firstRow;
- }
-
- sb.append("select * from ( ");
-
- sb.append("select ");
- if (request.isDistinct()) {
- sb.append("distinct ");
- }
-
- sb.append(ROW_NUMBER_OVER);
- sb.append(request.getDbOrderBy());
- sb.append(ROW_NUMBER_AS);
-
- sb.append(dbSql);
-
- sb.append(" ) ");
- sb.append(rowNumberWindowAlias);
- sb.append(" where ");
- if (firstRow > 0) {
- sb.append(" rn > ").append(firstRow);
- if (lastRow > 0) {
- sb.append(" and ");
- }
- }
- if (lastRow > 0) {
- sb.append(" rn <= ").append(lastRow);
- }
-
- String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
-
- return new SqlLimitResponse(sql, true);
- }
-}
diff --git a/src/main/java/io/ebean/config/dbplatform/RownumSqlLimiter.java b/src/main/java/io/ebean/config/dbplatform/RownumSqlLimiter.java
deleted file mode 100644
index ef7656782..000000000
--- a/src/main/java/io/ebean/config/dbplatform/RownumSqlLimiter.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.ebean.config.dbplatform;
-
-/**
- * Add ROWNUM column etc around SQL query to limit results.
- */
-public class RownumSqlLimiter implements SqlLimiter {
-
- private final String rnum;
-
- private final boolean useFirstRowsHint;
-
- /**
- * Create with default inner rownum column alias and used FIRST_ROWS hint.
- */
- public RownumSqlLimiter() {
- this("rn_", true);
- }
-
- /**
- * Specify the inner rownum column alias and whether to include the FIRST_ROWS
- * hint.
- */
- public RownumSqlLimiter(String rnum, boolean useFirstRowsHint) {
- this.rnum = rnum;
- this.useFirstRowsHint = useFirstRowsHint;
- }
-
- @Override
- public SqlLimitResponse limit(SqlLimitRequest request) {
-
- // select *
- // from ( select /*+ FIRST_ROWS(n) */ ROWNUM rnum, a.*
- // from ( your_query_goes_here,
- // with order by ) a
- // where ROWNUM <=
- // :MAX_ROW_TO_FETCH )
- // where rnum >= :MIN_ROW_TO_FETCH;
-
- String dbSql = request.getDbSql();
-
- StringBuilder sb = new StringBuilder(60 + dbSql.length());
-
- int firstRow = request.getFirstRow();
-
- int lastRow = request.getMaxRows();
- if (lastRow > 0) {
- lastRow += firstRow;
- }
-
- sb.append("select * from ( ");
-
- sb.append("select ");
- if (useFirstRowsHint && request.getMaxRows() > 0) {
- sb.append("/*+ FIRST_ROWS(").append(request.getMaxRows()).append(") */ ");
- }
-
- sb.append("rownum ").append(rnum).append(", a.* ");
- sb.append(" from (");
-
- sb.append(" select ");
- if (request.isDistinct()) {
- sb.append("distinct ");
- }
- sb.append(dbSql);
-
- sb.append(NEW_LINE).append(" ) a ");
- if (lastRow > 0) {
- sb.append(" where rownum <= ").append(lastRow);
- }
- sb.append(" ) ");
- if (firstRow > 0) {
- sb.append(" where ");
- sb.append(rnum).append(" > ").append(firstRow);
- }
-
- String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
-
- return new SqlLimitResponse(sql, true);
- }
-
-}
diff --git a/src/main/java/io/ebean/config/dbplatform/oracle/Oracle11Platform.java b/src/main/java/io/ebean/config/dbplatform/oracle/Oracle11Platform.java
new file mode 100644
index 000000000..aa3ed1b2e
--- /dev/null
+++ b/src/main/java/io/ebean/config/dbplatform/oracle/Oracle11Platform.java
@@ -0,0 +1,16 @@
+package io.ebean.config.dbplatform.oracle;
+
+import io.ebean.annotation.Platform;
+
+/**
+ * Oracle 11 platform using rownum sql limiting.
+ */
+public class Oracle11Platform extends OraclePlatform {
+
+ public Oracle11Platform() {
+ super();
+ this.platform = Platform.ORACLE11;
+ this.columnAliasPrefix = "c";
+ this.sqlLimiter = new OracleRownumSqlLimiter();
+ }
+}
diff --git a/src/main/java/io/ebean/config/dbplatform/oracle/OracleAnsiSqlRowsLimiter.java b/src/main/java/io/ebean/config/dbplatform/oracle/OracleAnsiSqlRowsLimiter.java
new file mode 100644
index 000000000..0a23ce87f
--- /dev/null
+++ b/src/main/java/io/ebean/config/dbplatform/oracle/OracleAnsiSqlRowsLimiter.java
@@ -0,0 +1,34 @@
+package io.ebean.config.dbplatform.oracle;
+
+import io.ebean.config.dbplatform.SqlLimitRequest;
+import io.ebean.config.dbplatform.SqlLimitResponse;
+import io.ebean.config.dbplatform.SqlLimiter;
+
+/**
+ * Use ANSI offset rows syntax.
+ */
+class OracleAnsiSqlRowsLimiter implements SqlLimiter {
+
+ @Override
+ public SqlLimitResponse limit(SqlLimitRequest request) {
+
+ String dbSql = request.getDbSql();
+ StringBuilder sb = new StringBuilder(50 + dbSql.length());
+ int firstRow = request.getFirstRow();
+ int maxRows = request.getMaxRows();
+
+ sb.append("select ");
+ if (request.isDistinct()) {
+ sb.append("distinct ");
+ }
+ sb.append(dbSql);
+ if (firstRow > 0) {
+ sb.append(" offset ").append(firstRow).append(" rows");
+ }
+ if (maxRows > 0) {
+ sb.append(" fetch next ").append(maxRows).append(" rows only");
+ }
+ return new SqlLimitResponse(sb.toString(), false);
+ }
+
+}
diff --git a/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java b/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java
index 1112688ce..ab39dbf0d 100644
--- a/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java
+++ b/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java
@@ -9,7 +9,6 @@ import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.PlatformIdGenerator;
-import io.ebean.config.dbplatform.RownumSqlLimiter;
import io.ebean.config.dbplatform.SqlErrorCodes;
import javax.sql.DataSource;
@@ -23,11 +22,12 @@ public class OraclePlatform extends DatabasePlatform {
public OraclePlatform() {
super();
this.platform = Platform.ORACLE;
+ this.columnAliasPrefix = null;
this.supportsDeleteTableAlias = true;
this.maxTableNameLength = 30;
this.maxConstraintNameLength = 30;
this.dbEncrypt = new OracleDbEncrypt();
- this.sqlLimiter = new RownumSqlLimiter();
+ this.sqlLimiter = new OracleAnsiSqlRowsLimiter();
this.basicSqlLimiter = new BasicSqlAnsiLimiter();
this.historySupport = new OracleDbHistorySupport();
this.truncateTable = "truncate table %s cascade";
diff --git a/src/main/java/io/ebean/config/dbplatform/oracle/OracleRownumSqlLimiter.java b/src/main/java/io/ebean/config/dbplatform/oracle/OracleRownumSqlLimiter.java
new file mode 100644
index 000000000..7f798f897
--- /dev/null
+++ b/src/main/java/io/ebean/config/dbplatform/oracle/OracleRownumSqlLimiter.java
@@ -0,0 +1,54 @@
+package io.ebean.config.dbplatform.oracle;
+
+import io.ebean.config.dbplatform.SqlLimitRequest;
+import io.ebean.config.dbplatform.SqlLimitResponse;
+import io.ebean.config.dbplatform.SqlLimiter;
+
+/**
+ * Add ROWNUM column etc around SQL query to limit results.
+ */
+class OracleRownumSqlLimiter implements SqlLimiter {
+
+ @Override
+ public SqlLimitResponse limit(SqlLimitRequest request) {
+
+ // select *
+ // from ( select /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum
+ // from ( your_query_goes_here,
+ // with order by ) a
+ // where ROWNUM <=
+ // :MAX_ROW_TO_FETCH )
+ // where rnum >= :MIN_ROW_TO_FETCH;
+
+ String dbSql = request.getDbSql();
+
+ StringBuilder sb = new StringBuilder(60 + dbSql.length());
+ int firstRow = request.getFirstRow();
+ int lastRow = request.getMaxRows();
+ if (lastRow > 0) {
+ lastRow += firstRow;
+ }
+
+ sb.append("select * from (select ");
+ if (request.getMaxRows() > 0) {
+ sb.append("/*+ FIRST_ROWS(").append(request.getMaxRows()).append(") */ ");
+ }
+
+ sb.append("a.*, rownum rn_ from (select ");
+ if (request.isDistinct()) {
+ sb.append("distinct ");
+ }
+ sb.append(dbSql).append(") a ");
+ if (lastRow > 0) {
+ sb.append(" where rownum <= ").append(lastRow);
+ }
+ sb.append(") ");
+ if (firstRow > 0) {
+ sb.append(" where rn_ > ").append(firstRow);
+ }
+
+ String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
+ return new SqlLimitResponse(sql, false);
+ }
+
+}
diff --git a/src/main/java/io/ebeaninternal/dbmigration/DefaultDbMigration.java b/src/main/java/io/ebeaninternal/dbmigration/DefaultDbMigration.java
index dec46fef6..43def5067 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/DefaultDbMigration.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/DefaultDbMigration.java
@@ -18,6 +18,7 @@ import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
import io.ebean.config.dbplatform.mysql.MySql55Platform;
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
+import io.ebean.config.dbplatform.oracle.Oracle11Platform;
import io.ebean.config.dbplatform.oracle.OraclePlatform;
import io.ebean.config.dbplatform.postgres.Postgres9Platform;
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
@@ -826,6 +827,8 @@ public class DefaultDbMigration implements DbMigration {
return new MySqlPlatform();
case ORACLE:
return new OraclePlatform();
+ case ORACLE11:
+ return new Oracle11Platform();
case SQLANYWHERE:
return new SqlAnywherePlatform();
case SQLSERVER16:
diff --git a/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java b/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java
index 9c0e4b439..5c6e2f3b0 100644
--- a/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java
+++ b/src/main/java/io/ebeaninternal/server/core/DatabasePlatformFactory.java
@@ -11,6 +11,7 @@ import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
import io.ebean.config.dbplatform.mysql.MySql55Platform;
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
+import io.ebean.config.dbplatform.oracle.Oracle11Platform;
import io.ebean.config.dbplatform.oracle.OraclePlatform;
import io.ebean.config.dbplatform.postgres.Postgres8Platform;
import io.ebean.config.dbplatform.postgres.Postgres9Platform;
@@ -93,7 +94,10 @@ public class DatabasePlatformFactory {
if (dbName.equals("postgres8") || dbName.equals("postgres83")) {
return new Postgres8Platform();
}
- if (dbName.equals("oracle") || dbName.equals("oracle10") || dbName.equals("oracle9")) {
+ if (dbName.equals("oracle11") || dbName.equals("oracle10") || dbName.equals("oracle9")) {
+ return new Oracle11Platform();
+ }
+ if (dbName.equals("oracle")) {
return new OraclePlatform();
}
if (dbName.equals("sqlserver16")) {
diff --git a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
index 811a36acf..24b53f4e7 100644
--- a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
+++ b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
@@ -533,7 +533,7 @@ public class InternalConfiguration {
}
return new NoDataTimeZone();
}
- if (getPlatform() == Platform.ORACLE) {
+ if (getPlatform().base() == Platform.ORACLE) {
return new CloneDataTimeZone(tz);
} else {
return new SimpleDataTimeZone(tz);
diff --git a/src/main/java/io/ebeaninternal/server/core/PlatformDdlBuilder.java b/src/main/java/io/ebeaninternal/server/core/PlatformDdlBuilder.java
index 543d9bf02..802e63662 100644
--- a/src/main/java/io/ebeaninternal/server/core/PlatformDdlBuilder.java
+++ b/src/main/java/io/ebeaninternal/server/core/PlatformDdlBuilder.java
@@ -39,6 +39,7 @@ public class PlatformDdlBuilder {
case NUODB:
return new NuoDbDdl(platform);
case ORACLE:
+ case ORACLE11:
return new Oracle10Ddl(platform);
case SQLITE:
return new SQLiteDdl(platform);
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java
index 40ae04a1d..2c85e7963 100644
--- a/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java
@@ -56,4 +56,17 @@ abstract class BaseDbExpression implements DbExpressionHandler {
sb.append(')');
return sb.toString();
}
+
+ /**
+ * Concat using operator for Oracle and Postgres.
+ */
+ String concatOperator(String property0, String separator, String property1, String suffix) {
+ StringBuilder sb = new StringBuilder(40);
+ sb.append("(").append(property0).append("||'").append(separator).append("'||").append(property1);
+ if (suffix != null && !suffix.isEmpty()) {
+ sb.append("||'").append(suffix).append('\'');
+ }
+ sb.append(')');
+ return sb.toString();
+ }
}
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandlerFactory.java b/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandlerFactory.java
index 0d7872416..5f1de2883 100644
--- a/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandlerFactory.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandlerFactory.java
@@ -23,6 +23,7 @@ public class DbExpressionHandlerFactory {
case MYSQL:
return new MySqlDbExpression();
case ORACLE:
+ case ORACLE11:
return new OracleDbExpression();
case SQLSERVER16:
case SQLSERVER17:
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java
index fb65c7c03..0c7e43b65 100644
--- a/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java
@@ -10,7 +10,6 @@ class H2DbExpression extends BasicDbExpression {
@Override
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
-
bitwiseFunction(request, propName, operator, compare);
}
}
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java
index 168f01aaf..3ec4b4071 100644
--- a/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java
@@ -9,6 +9,11 @@ import io.ebeaninternal.server.expression.Op;
*/
public class OracleDbExpression extends BaseDbExpression {
+ @Override
+ public String concat(String property0, String separator, String property1, String suffix) {
+ return concatOperator(property0, separator, property1, suffix);
+ }
+
@Override
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java
index adac971b5..54270ee5c 100644
--- a/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java
@@ -8,6 +8,11 @@ import io.ebeaninternal.server.expression.Op;
*/
public class PostgresDbExpression extends BaseDbExpression {
+ @Override
+ public String concat(String property0, String separator, String property1, String suffix) {
+ return concatOperator(property0, separator, property1, suffix);
+ }
+
@Override
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
@@ -62,15 +67,4 @@ public class PostgresDbExpression extends BaseDbExpression {
}
}
- @Override
- public String concat(String property0, String separator, String property1, String suffix) {
- StringBuilder sb = new StringBuilder();
- sb.append("(").append(property0).append("||'").append(separator).append("'||").append(property1);
-
- if (suffix != null && !suffix.isEmpty()) {
- sb.append("||'").append(suffix).append('\'');
- }
- sb.append(')');
- return sb.toString();
- }
}
diff --git a/src/test/java/io/ebean/BaseTestCase.java b/src/test/java/io/ebean/BaseTestCase.java
index 6a1077bfc..6c1326d77 100644
--- a/src/test/java/io/ebean/BaseTestCase.java
+++ b/src/test/java/io/ebean/BaseTestCase.java
@@ -175,7 +175,7 @@ public abstract class BaseTestCase {
* so tests that do this need to be skipped for SQL Server.
*/
public boolean isSqlServer() {
- return Platform.SQLSERVER == platform().base();
+ return Platform.SQLSERVER == platform();
}
public boolean isH2() {
@@ -203,7 +203,7 @@ public abstract class BaseTestCase {
}
public boolean isMySql() {
- return Platform.MYSQL == platform().base();
+ return Platform.MYSQL == platform();
}
public boolean isHana() {
@@ -242,7 +242,7 @@ public abstract class BaseTestCase {
}
protected Platform platform() {
- return spiEbeanServer().getDatabasePlatform().getPlatform();
+ return spiEbeanServer().getDatabasePlatform().getPlatform().base();
}
protected IdType idType() {
diff --git a/src/test/java/io/ebean/EbeanServer_eqlTest.java b/src/test/java/io/ebean/EbeanServer_eqlTest.java
index d0f673b79..1455c4770 100644
--- a/src/test/java/io/ebean/EbeanServer_eqlTest.java
+++ b/src/test/java/io/ebean/EbeanServer_eqlTest.java
@@ -27,7 +27,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
assertSql(query).startsWith("select top 100 ");
assertSql(query).endsWith("order by t0.id");
} else if (isOracle()) {
- assertSql(query).contains("where rownum <= 100");
+ assertSql(query).contains(" fetch next 100 rows only");
} else {
assertSql(query).endsWith("order by t0.id limit 100");
}
@@ -45,7 +45,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
assertSql(query).startsWith("select top 10 ");
assertSql(query).endsWith("order by t0.id");
} else if (isOracle()) {
- assertSql(query).contains("where rownum <= 10");
+ assertSql(query).contains(" fetch next 10 rows only");
} else {
assertSql(query).endsWith("order by t0.id limit 10");
}
@@ -62,8 +62,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
if (isSqlServer()) {
assertSql(query).endsWith("order by t0.id offset 3 rows fetch next 10 rows only");
} else if (isOracle()) {
- assertSql(query).contains("where rownum <= 13");
- assertSql(query).contains("where rn_ > 3");
+ assertSql(query).contains("offset 3 rows fetch next 10 rows only");
} else {
assertSql(query).endsWith("order by t0.id limit 10 offset 3");
}
@@ -83,8 +82,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
if (isSqlServer()) {
assertSql(query).endsWith("order by t0.name offset 3 rows fetch next 10 rows only");
} else if (isOracle()) {
- assertSql(query).contains("where rownum <= 13");
- assertSql(query).contains("where rn_ > 3");
+ assertSql(query).contains("offset 3 rows fetch next 10 rows only");
} else {
assertSql(query).endsWith("order by t0.name limit 10 offset 3");
}
@@ -110,8 +108,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
if (isSqlServer()) {
assertSql(query).endsWith("order by t0.name, t0.id offset 3 rows fetch next 10 rows only");
} else if (isOracle()) {
- assertSql(query).contains("where rownum <= 13");
- assertSql(query).contains("where rn_ > 3");
+ assertSql(query).contains("offset 3 rows fetch next 10 rows only");
} else {
assertSql(query).endsWith("order by t0.name, t0.id limit 10 offset 3");
}
@@ -140,8 +137,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
if (isSqlServer()) {
assertSql(query).endsWith("from o_customer t0 order by t0.id offset 3 rows fetch next 10 rows only");
} else if (isOracle()) {
- assertSql(query).contains("where rownum <= 13");
- assertSql(query).contains("where rn_ > 3");
+ assertSql(query).contains("offset 3 rows fetch next 10 rows only");
} else {
assertSql(query).endsWith("from o_customer t0 limit 10 offset 3");
}
@@ -159,7 +155,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
if (isSqlServer()) {
assertSql(query).startsWith("select top 10 ");
} else if (isOracle()) {
- assertSql(query).contains(" a where rownum <= 10");
+ assertSql(query).contains("fetch next 10 rows only");
} else {
assertSql(query).endsWith("limit 10");
}
diff --git a/src/test/java/io/ebeaninternal/server/expression/platform/H2DbExpressionTest.java b/src/test/java/io/ebeaninternal/server/expression/platform/H2DbExpressionTest.java
new file mode 100644
index 000000000..9cd0f687c
--- /dev/null
+++ b/src/test/java/io/ebeaninternal/server/expression/platform/H2DbExpressionTest.java
@@ -0,0 +1,18 @@
+package io.ebeaninternal.server.expression.platform;
+
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class H2DbExpressionTest {
+
+ H2DbExpression expression = new H2DbExpression();
+
+ @Test
+ public void concat() {
+ assertThat(expression.concat("p0", ",", "q1", "suffix")).isEqualTo("concat(p0,',',q1,'suffix')");
+ assertThat(expression.concat("p0", ",", "q1", null)).isEqualTo("concat(p0,',',q1)");
+ assertThat(expression.concat("p0", ",", "q1", "")).isEqualTo("concat(p0,',',q1)");
+ }
+}
diff --git a/src/test/java/io/ebeaninternal/server/expression/platform/OracleDbExpressionTest.java b/src/test/java/io/ebeaninternal/server/expression/platform/OracleDbExpressionTest.java
new file mode 100644
index 000000000..6608927c2
--- /dev/null
+++ b/src/test/java/io/ebeaninternal/server/expression/platform/OracleDbExpressionTest.java
@@ -0,0 +1,18 @@
+package io.ebeaninternal.server.expression.platform;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class OracleDbExpressionTest {
+
+ OracleDbExpression expression = new OracleDbExpression();
+
+ @Test
+ public void concat() {
+ assertThat(expression.concat("p0", ",", "q1", "suffix")).isEqualTo("(p0||','||q1||'suffix')");
+ assertThat(expression.concat("p0", ",", "q1", null)).isEqualTo("(p0||','||q1)");
+ assertThat(expression.concat("p0", ",", "q1", "")).isEqualTo("(p0||','||q1)");
+ }
+
+}
diff --git a/src/test/java/io/ebeaninternal/server/expression/platform/PostgresDbExpressionTest.java b/src/test/java/io/ebeaninternal/server/expression/platform/PostgresDbExpressionTest.java
new file mode 100644
index 000000000..e9e4ae2d4
--- /dev/null
+++ b/src/test/java/io/ebeaninternal/server/expression/platform/PostgresDbExpressionTest.java
@@ -0,0 +1,17 @@
+package io.ebeaninternal.server.expression.platform;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PostgresDbExpressionTest {
+
+ PostgresDbExpression expression = new PostgresDbExpression();
+
+ @Test
+ public void concat() {
+ assertThat(expression.concat("p0", ",", "p1", "suffix")).isEqualTo("(p0||','||p1||'suffix')");
+ assertThat(expression.concat("p0", ",", "p1", null)).isEqualTo("(p0||','||p1)");
+ assertThat(expression.concat("p0", ",", "p1", "")).isEqualTo("(p0||','||p1)");
+ }
+}
diff --git a/src/test/java/main/StartOracle.java b/src/test/java/main/StartOracle.java
index ab08b1b18..df489be07 100644
--- a/src/test/java/main/StartOracle.java
+++ b/src/test/java/main/StartOracle.java
@@ -8,10 +8,9 @@ public class StartOracle {
public static void main(String[] args) {
OracleConfig config = new OracleConfig();
-// config.setImage("quillbuilduser/oracle-18-xe:latest");
config.setUser("test_ebean");
OracleContainer container = new OracleContainer(config);
- container.start();//WithDropCreate();
+ container.startWithDropCreate();
}
}
diff --git a/src/test/java/org/tests/batchinsert/TestBatchInsertFlush.java b/src/test/java/org/tests/batchinsert/TestBatchInsertFlush.java
index 8f5e667f4..dc04e0b79 100644
--- a/src/test/java/org/tests/batchinsert/TestBatchInsertFlush.java
+++ b/src/test/java/org/tests/batchinsert/TestBatchInsertFlush.java
@@ -205,7 +205,7 @@ public class TestBatchInsertFlush extends BaseTestCase {
}
@Test
- @IgnorePlatform(Platform.SQLSERVER)
+ @IgnorePlatform({Platform.SQLSERVER, Platform.ORACLE})
public void noflushWhenIdIsLoaded() {
EbeanServer server = Ebean.getDefaultServer();
diff --git a/src/test/java/org/tests/lazyforeignkeys/MainEntity.java b/src/test/java/org/tests/lazyforeignkeys/MainEntity.java
index 3fa760583..bacfbdf9f 100644
--- a/src/test/java/org/tests/lazyforeignkeys/MainEntity.java
+++ b/src/test/java/org/tests/lazyforeignkeys/MainEntity.java
@@ -21,7 +21,7 @@ public class MainEntity {
@SoftDelete
@Formula(select = "${ta}.id is null")
- @Formula(select = "CASE WHEN ${ta}.id is null THEN 1 ELSE 0 END", platforms = Platform.SQLSERVER17)
+ @Formula(select = "CASE WHEN ${ta}.id is null THEN 1 ELSE 0 END", platforms = {Platform.SQLSERVER17, Platform.ORACLE})
// evaluates to true in a left join if bean has been deleted.
boolean deleted;
diff --git a/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java b/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java
index 207d454dd..679556fe2 100644
--- a/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java
+++ b/src/test/java/org/tests/lazyforeignkeys/TestLazyForeignKeys.java
@@ -57,14 +57,14 @@ public class TestLazyForeignKeys extends BaseTestCase {
assertFalse(rel1.getEntity1().isDeleted());
assertTrue(rel1.getEntity2().isDeleted());
- List loggedSql = LoggedSqlCollector.stop();
- assertThat(loggedSql).hasSize(3);
- assertThat(loggedSql.get(0)).contains("select t0.id, t0.attr1, t0.id1, t0.id2 from main_entity_relation");
- if (isSqlServer()) {
- assertThat(loggedSql.get(1)).contains("select t0.id, t0.attr1, t0.attr2, CASE WHEN t0.id is null THEN 1 ELSE 0 END from main_entity t0");
+ List sql = LoggedSqlCollector.stop();
+ assertThat(sql).hasSize(3);
+ assertSql(sql.get(0)).contains("select t0.id, t0.attr1, t0.id1, t0.id2 from main_entity_relation");
+ if (isSqlServer() || isOracle()) {
+ assertSql(sql.get(1)).contains("select t0.id, t0.attr1, t0.attr2, CASE WHEN t0.id is null THEN 1 ELSE 0 END from main_entity t0");
} else {
- assertThat(loggedSql.get(1)).contains("select t0.id, t0.attr1, t0.attr2, t0.id is null from main_entity t0");
- assertThat(loggedSql.get(2)).contains("select t0.id, t0.attr1, t0.attr2, t0.id is null from main_entity t0");
+ assertSql(sql.get(1)).contains("select t0.id, t0.attr1, t0.attr2, t0.id is null from main_entity t0");
+ assertSql(sql.get(2)).contains("select t0.id, t0.attr1, t0.attr2, t0.id is null from main_entity t0");
}
}
diff --git a/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java b/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java
index bda886770..463f73d88 100644
--- a/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java
+++ b/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java
@@ -370,7 +370,7 @@ public class TestCacheViaComplexNaturalKey3 extends BaseTestCase {
if (isH2()) {
assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku,'-',t0.code) in (?,?) order by t0.sku desc; --bind(def,Array[2]={2-1000,3-1000})");
- } else if (isPostgres()) {
+ } else if (isPostgres() || isOracle()) {
assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and (t0.sku||'-'||t0.code)");
} else if (isHana()) {
assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku, '-'||t0.code)");
@@ -413,7 +413,7 @@ public class TestCacheViaComplexNaturalKey3 extends BaseTestCase {
if (isH2()) {
assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku,':',t0.code,'-foo') in (?,?) order by t0.sku desc; --bind(def,Array[2]={2:1000-foo,3:1000-foo})");
- } else if (isPostgres()){
+ } else if (isPostgres() || isOracle()){
assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and (t0.sku||':'||t0.code||'-foo')");
} else if (isHana()){
assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku, ':'||t0.code||'-foo')");
diff --git a/src/test/java/org/tests/model/history/TestHistoryOneToMany.java b/src/test/java/org/tests/model/history/TestHistoryOneToMany.java
index 50f0017f7..ea6d6f20f 100644
--- a/src/test/java/org/tests/model/history/TestHistoryOneToMany.java
+++ b/src/test/java/org/tests/model/history/TestHistoryOneToMany.java
@@ -2,6 +2,8 @@ package org.tests.model.history;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
+import io.ebean.annotation.IgnorePlatform;
+import io.ebean.annotation.Platform;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Test;
@@ -12,6 +14,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class TestHistoryOneToMany extends BaseTestCase {
+ @IgnorePlatform(Platform.ORACLE)
@Test
public void test() {
diff --git a/src/test/java/org/tests/model/nofk/EUserNoFkSoftDel.java b/src/test/java/org/tests/model/nofk/EUserNoFkSoftDel.java
index 214dd289c..f3eea2bcd 100644
--- a/src/test/java/org/tests/model/nofk/EUserNoFkSoftDel.java
+++ b/src/test/java/org/tests/model/nofk/EUserNoFkSoftDel.java
@@ -19,7 +19,7 @@ public class EUserNoFkSoftDel {
@SoftDelete
@Formula(select = "${ta}.user_id is null")
- @Formula(select = "CASE WHEN ${ta}.user_id is null THEN 1 ELSE 0 END", platforms = Platform.SQLSERVER17)
+ @Formula(select = "CASE WHEN ${ta}.user_id is null THEN 1 ELSE 0 END", platforms = {Platform.SQLSERVER17, Platform.ORACLE})
// evaluates to true in a left join if bean has been deleted.
boolean deleted;
diff --git a/src/test/java/org/tests/model/nofk/TestNoFk.java b/src/test/java/org/tests/model/nofk/TestNoFk.java
index a2315eb05..e9ed12dbe 100644
--- a/src/test/java/org/tests/model/nofk/TestNoFk.java
+++ b/src/test/java/org/tests/model/nofk/TestNoFk.java
@@ -27,8 +27,9 @@ public class TestNoFk extends BaseTestCase {
Ebean.find(EUserNoFk.class).delete();
Ebean.find(EUserNoFkSoftDel.class).delete();
- Ebean.createSqlUpdate("delete from efile_no_fk_euser_no_fk").execute();
- Ebean.createSqlUpdate("delete from efile_no_fk_euser_no_fk_soft_del").execute();
+ DB.sqlUpdate("delete from efile_no_fk_euser_no_fk").execute();
+ String tabName = isOracle() ? "efile_no_fk_euser_no_fk_soft_d" : "efile_no_fk_euser_no_fk_soft_del";
+ DB.sqlUpdate("delete from " + tabName).execute();
// There are two user accounts persisted in our database
EUserNoFk root = new EUserNoFk();
diff --git a/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanRemove.java b/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanRemove.java
index 43c642add..7c0828c25 100644
--- a/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanRemove.java
+++ b/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanRemove.java
@@ -39,7 +39,7 @@ public class TestOneToOneOrphanRemove extends BaseTestCase {
assertSqlBind(sql.get(1));
assertSql(sql.get(2)).contains("update oto_cust set version=? where cid=? and version=?");
assertThat(sql.get(3)).contains("insert into oto_cust_address ");
- assertThat(sql.get(4)).contains("-- bind(other1");
+ assertThat(sql.get(4)).contains("-- bind(");
jack.setAddress(null);
Ebean.save(jack);
diff --git a/src/test/java/org/tests/query/TestQueryOrderById.java b/src/test/java/org/tests/query/TestQueryOrderById.java
index 05e2a8318..3c536a6f8 100644
--- a/src/test/java/org/tests/query/TestQueryOrderById.java
+++ b/src/test/java/org/tests/query/TestQueryOrderById.java
@@ -22,7 +22,7 @@ public class TestQueryOrderById extends BaseTestCase {
query.findList();
if (isSqlServer()) {
assertSql(query).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id offset 1 rows fetch next 5 rows only");
- } else {
+ } else if (!isOracle()) {
assertSql(query).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id limit 5 offset 1");
}
}
@@ -39,7 +39,7 @@ public class TestQueryOrderById extends BaseTestCase {
query.findList();
if (isSqlServer()) {
assertSql(query).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id offset 1 rows fetch next 5 rows only");
- } else {
+ } else if (!isOracle()) {
assertSql(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/finder/TestCustomerFinder.java b/src/test/java/org/tests/query/finder/TestCustomerFinder.java
index 1e9e0cdbc..c1d323164 100644
--- a/src/test/java/org/tests/query/finder/TestCustomerFinder.java
+++ b/src/test/java/org/tests/query/finder/TestCustomerFinder.java
@@ -229,8 +229,10 @@ public class TestCustomerFinder extends BaseTestCase {
assertThat(metricsJson).contains("\"name\":\"txn.main\"");
assertThat(metricsJson).contains("\"name\":\"orm.Customer.findList\"");
assertThat(metricsJson).contains("\"loc\":\"CustomerFinder.byNameStatus(CustomerFinder.java:44)\"");
- assertThat(metricsJson).contains("\"hash\":\"cc20eb930403cfd418db2d0475c6e26a\"");
- assertThat(metricsJson).contains("\"sql\":\"select t0.id, t0.status,");
+ if (!isOracle()) {
+ assertThat(metricsJson).contains("\"hash\":\"cc20eb930403cfd418db2d0475c6e26a\"");
+ assertThat(metricsJson).contains("\"sql\":\"select t0.id, t0.status,");
+ }
}
@Test
diff --git a/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java b/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java
index 10f2ad09d..0fbd0bfe5 100644
--- a/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java
+++ b/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java
@@ -191,8 +191,7 @@ public class TestQuerySingleAttribute extends BaseTestCase {
if (isSqlServer()) {
assertThat(sqlOf(query)).contains("select distinct top 100 t0.id from o_customer t0");
} else if (isOracle()) {
- assertThat(sqlOf(query)).contains("from ( select distinct t0.id from o_customer t0");
- assertThat(sqlOf(query)).contains("where rownum <= 100");
+ assertThat(sqlOf(query)).contains("select distinct t0.id from o_customer t0 fetch next 100 rows only");
} else {
assertThat(sqlOf(query)).contains("select distinct t0.id from o_customer t0 limit 100");
}
@@ -271,7 +270,7 @@ public class TestQuerySingleAttribute extends BaseTestCase {
if (isSqlServer()) {
assertThat(sqlOf(query)).contains("select top 100 t0.id from o_customer t0");
} else if (isOracle()) {
- assertThat(sqlOf(query)).contains("where rownum <= 100");
+ assertThat(sqlOf(query)).contains("fetch next 100 rows only");
} else {
assertThat(sqlOf(query)).contains("select t0.id from o_customer t0 limit 100");
}
@@ -583,16 +582,23 @@ public class TestQuerySingleAttribute extends BaseTestCase {
.where().isNotNull("customer.billingAddress.line1").query()
.setCountDistinct(CountDistinctOrder.ATTR_DESC)
.findSingleAttributeList();
- assertThat(sqlOf(query)).contains("select r1.attribute_, count(*) from ("
- + "select t2.line_1 as attribute_ from contact t0 "
- + "join o_customer t1 on t1.id = t0.customer_id "
- + "left join o_address t2 on t2.id = t1.billing_address_id "
- + "where t2.line_1 is not null"
- + ") r1 group by r1.attribute_ order by r1.attribute_ desc ");
+
+ if (isOracle()) {
+ assertSql(query).contains("select r1.attribute_, count(*) from (select t2.line_1 as attribute_ from contact t0 join o_customer t1 on t1.id = t0.customer_id left join o_address t2 on t2.id = t1.billing_address_id where t2.line_1 is not null) r1 group by r1.attribute_ order by r1.attribute_ desc offset 1 rows fetch next 2 rows only");
+ } else {
+ assertSql(query).contains("select r1.attribute_, count(*) from ("
+ + "select t2.line_1 as attribute_ from contact t0 "
+ + "join o_customer t1 on t1.id = t0.customer_id "
+ + "left join o_address t2 on t2.id = t1.billing_address_id "
+ + "where t2.line_1 is not null"
+ + ") r1 group by r1.attribute_ order by r1.attribute_ desc ");
+ }
if (isSqlServer()) {
assertThat(sqlOf(query)).endsWith(" fetch next 2 rows only");
} else if (isDb2()) {
assertSql(query).endsWith("FETCH FIRST 2 ROWS ONLY");
+ } else if (isOracle()) {
+ assertSql(query).contains(" offset 1 rows fetch next 2 rows only");
} else {
assertThat(sqlOf(query)).endsWith(" limit 2 offset 1");
}
diff --git a/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java b/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java
index 85a8a8796..58b8c2285 100644
--- a/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java
+++ b/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java
@@ -219,7 +219,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
assertSql(query).contains("top 100 ");
assertSql(query).contains("order by o.ship_date desc");
} else if (isOracle()) {
- assertSql(query).contains("a where rownum <= 100 )");
+ assertSql(query).contains("fetch next 100 rows only");
} else {
assertSql(query).contains("order by o.ship_date desc limit 100");
}
@@ -254,7 +254,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
assertSql(query).contains("top 100 ");
assertSql(query).contains("order by o.ship_date desc, o.id");
} else if (isOracle()) {
- assertSql(query).contains("a where rownum <= 100 )");
+ assertSql(query).contains("fetch next 100 rows only");
} else {
assertSql(query).contains("order by o.ship_date desc, o.id limit 100");
}
@@ -356,7 +356,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
assertThat(sqlOf(query)).contains("select top 100 ");
assertThat(sqlOf(query)).contains("order by o.id desc");
} else if (isOracle()) {
- assertThat(sqlOf(query)).contains("a where rownum <= 100 )");
+ assertThat(sqlOf(query)).contains("fetch next 100 rows only");
} else {
assertThat(sqlOf(query)).contains("order by o.id desc limit 100");
}
diff --git a/src/test/java/org/tests/transaction/TestNestedSubTransaction.java b/src/test/java/org/tests/transaction/TestNestedSubTransaction.java
index a30d5a104..313019b5f 100644
--- a/src/test/java/org/tests/transaction/TestNestedSubTransaction.java
+++ b/src/test/java/org/tests/transaction/TestNestedSubTransaction.java
@@ -65,7 +65,7 @@ public class TestNestedSubTransaction extends BaseTestCase {
}
- @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA})
+ @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA, Platform.ORACLE})
@Test
public void nestedUseSavepoint_doubleNested_rollbackCommit() {
@@ -102,7 +102,7 @@ public class TestNestedSubTransaction extends BaseTestCase {
}
}
- @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA})
+ @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA, Platform.ORACLE})
@Test
public void nestedUseSavepoint_doubleNested_commitRollback() {
@@ -139,7 +139,7 @@ public class TestNestedSubTransaction extends BaseTestCase {
}
}
- @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA})
+ @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA, Platform.ORACLE})
@Test
public void nestedUseSavepoint_nested_RequiresNew() {
@@ -175,7 +175,7 @@ public class TestNestedSubTransaction extends BaseTestCase {
assertNull(after);
}
- @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA})
+ @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.HANA, Platform.ORACLE})
@Test
public void nestedUseSavepoint() {