propertyMap);
+ /**
+ * Add expression for ANY of the given bit flags to be set.
+ *
+ * @param propertyName The property that holds the flags value
+ * @param flags The flags we are looking for
+ */
+ Expression bitwiseAny(String propertyName, long flags);
+
+ /**
+ * Add expression for ALL of the given bit flags to be set.
+ *
+ * @param propertyName The property that holds the flags value
+ * @param flags The flags we are looking for
+ */
+ Expression bitwiseAll(String propertyName, long flags);
+
+ /**
+ * Add bitwise AND expression of the given bit flags to compare with the match/mask.
+ *
+ * @param propertyName The property that holds the flags value
+ * @param flags The flags we are looking for
+ */
+ Expression bitwiseAnd(String propertyName, long flags, long match);
+
/**
* Add raw expression with a single parameter.
*
diff --git a/src/main/java/io/ebean/ExpressionList.java b/src/main/java/io/ebean/ExpressionList.java
index 4723ab212..711d23906 100644
--- a/src/main/java/io/ebean/ExpressionList.java
+++ b/src/main/java/io/ebean/ExpressionList.java
@@ -482,7 +482,7 @@ public interface ExpressionList {
/**
* Extended version for setDistinct in conjunction with "findSingleAttributeList";
- *
+ *
*
{@code
*
* List> orderStatusCount =
@@ -878,7 +878,7 @@ public interface ExpressionList {
/**
* In - using a subQuery.
- *
+ *
* This is exactly the same as in() and provided due to "in" being a Kotlin keyword
* (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
*/
@@ -888,7 +888,7 @@ public interface ExpressionList {
/**
* In - property has a value in the array of values.
- *
+ *
* This is exactly the same as in() and provided due to "in" being a Kotlin keyword
* (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
*/
@@ -898,7 +898,7 @@ public interface ExpressionList {
/**
* In - property has a value in the collection of values.
- *
+ *
* This is exactly the same as in() and provided due to "in" being a Kotlin keyword
* (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
*/
@@ -996,6 +996,53 @@ public interface ExpressionList {
*/
ExpressionList arrayIsNotEmpty(String propertyName);
+ /**
+ * Add expression for ANY of the given bit flags to be set.
+ * {@code
+ *
+ * where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
+ *
+ * }
+ *
+ * @param propertyName The property that holds the flags value
+ * @param flags The flags we are looking for
+ */
+ ExpressionList bitwiseAny(String propertyName, long flags);
+
+ /**
+ * Add expression for ALL of the given bit flags to be set.
+ *
+ *
{@code
+ *
+ * where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
+ *
+ * }
+ *
+ * @param propertyName The property that holds the flags value
+ * @param flags The flags we are looking for
+ */
+ ExpressionList bitwiseAll(String propertyName, long flags);
+
+ /**
+ * Add bitwise AND expression of the given bit flags to compare with the match/mask.
+ *
+ *
{@code
+ *
+ * // Flags Bulk + Size = Size
+ * // ... meaning Bulk is not set and Size is set
+ *
+ * long selectedFlags = BwFlags.HAS_BULK + BwFlags.HAS_SIZE;
+ * long mask = BwFlags.HAS_SIZE; // Only Size flag set
+ *
+ * where().bitwiseAnd("flags", selectedFlags, mask)
+ *
+ * }
+ *
+ * @param propertyName The property that holds the flags value
+ * @param flags The flags we are looking for
+ */
+ ExpressionList bitwiseAnd(String propertyName, long flags, long match);
+
/**
* Add raw expression with a single parameter.
*
diff --git a/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java b/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java
index 49bb47bf9..e61c9479e 100644
--- a/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java
+++ b/src/main/java/io/ebeaninternal/api/SpiExpressionRequest.java
@@ -1,8 +1,8 @@
package io.ebeaninternal.api;
-import io.ebeaninternal.server.core.DbExpressionHandler;
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;
+import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
import java.util.List;
diff --git a/src/main/java/io/ebeaninternal/server/core/BaseDbExpression.java b/src/main/java/io/ebeaninternal/server/core/BaseDbExpression.java
deleted file mode 100644
index fe2c97893..000000000
--- a/src/main/java/io/ebeaninternal/server/core/BaseDbExpression.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.ebeaninternal.server.core;
-
-/**
- * Not supported JSON or ARRAY expression handler.
- */
-abstract class BaseDbExpression implements DbExpressionHandler {
-
- private final String concatOperator;
-
- BaseDbExpression(String concatOperator) {
- this.concatOperator = concatOperator;
- }
-
- @Override
- public String getConcatOperator() {
- return concatOperator;
- }
-
-}
diff --git a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
index e9b423ece..ab0587d94 100644
--- a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
+++ b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
@@ -42,6 +42,8 @@ import io.ebeaninternal.server.deploy.parse.DeployInherit;
import io.ebeaninternal.server.deploy.parse.DeployUtil;
import io.ebeaninternal.server.dto.DtoBeanManager;
import io.ebeaninternal.server.expression.DefaultExpressionFactory;
+import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
+import io.ebeaninternal.server.expression.platform.DbExpressionHandlerFactory;
import io.ebeaninternal.server.persist.Binder;
import io.ebeaninternal.server.persist.DefaultPersister;
import io.ebeaninternal.server.persist.platform.MultiValueBind;
@@ -267,18 +269,7 @@ public class InternalConfiguration {
* Return the JSON expression handler for the given database platform.
*/
private DbExpressionHandler getDbExpressionHandler(DatabasePlatform databasePlatform) {
- Platform platform = databasePlatform.getPlatform();
- String concatOperator = databasePlatform.getConcatOperator();
- switch (platform) {
- case POSTGRES:
- return new PostgresDbExpression(concatOperator);
- case ORACLE:
- return new OracleDbExpression(concatOperator);
- case SQLSERVER:
- return new SqlServerDbExpression(concatOperator);
- default:
- return new BasicDbExpression(concatOperator);
- }
+ return DbExpressionHandlerFactory.from(databasePlatform);
}
private MultiValueBind createMultiValueBind(Platform platform) {
diff --git a/src/main/java/io/ebeaninternal/server/expression/BitwiseExpression.java b/src/main/java/io/ebeaninternal/server/expression/BitwiseExpression.java
new file mode 100644
index 000000000..073ee51df
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/expression/BitwiseExpression.java
@@ -0,0 +1,63 @@
+package io.ebeaninternal.server.expression;
+
+import io.ebeaninternal.api.SpiExpression;
+import io.ebeaninternal.api.SpiExpressionRequest;
+
+import java.io.IOException;
+
+/**
+ * Bitwise expression.
+ */
+class BitwiseExpression extends AbstractExpression {
+
+ protected final BitwiseOp operator;
+
+ private final String compare;
+
+ protected final long flags;
+
+ private final long match;
+
+ BitwiseExpression(String propertyName, BitwiseOp operator, long flags, String compare, long match) {
+ super(propertyName);
+ this.operator = operator;
+ this.flags = flags;
+ this.compare = compare;
+ this.match = match;
+ }
+
+ @Override
+ public void writeDocQuery(DocQueryContext context) throws IOException {
+ throw new IllegalStateException("Not supported for document queries");
+ }
+
+ @Override
+ public void queryPlanHash(StringBuilder builder) {
+ builder.append("Bitwise[");
+ builder.append(propName).append(" op:").append(operator).append(" cp:").append(compare);
+ builder.append(" ?2]");
+ }
+
+ @Override
+ public int queryBindHash() {
+ return Long.hashCode(flags);
+ }
+
+ @Override
+ public boolean isSameByBind(SpiExpression other) {
+ BitwiseExpression that = (BitwiseExpression) other;
+ return operator == that.operator && compare.equals(that.compare) && flags == that.flags && match == that.match;
+ }
+
+ @Override
+ public void addSql(SpiExpressionRequest request) {
+ // Use DB specific expression handling
+ request.getDbPlatformHandler().bitwise(request, propName, operator, flags, compare, match);
+ }
+
+ @Override
+ public void addBindValues(SpiExpressionRequest request) {
+ request.addBindValue(flags);
+ request.addBindValue(match);
+ }
+}
diff --git a/src/main/java/io/ebeaninternal/server/expression/BitwiseOp.java b/src/main/java/io/ebeaninternal/server/expression/BitwiseOp.java
new file mode 100644
index 000000000..c7a063f54
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/expression/BitwiseOp.java
@@ -0,0 +1,22 @@
+package io.ebeaninternal.server.expression;
+
+/**
+ * Bitwise expression operator.
+ */
+public enum BitwiseOp {
+
+ /**
+ * All flags are set (derived expression BITAND flags == flags).
+ */
+ ALL,
+
+ /**
+ * Any flags are set (derived expression BITAND flags != 0).
+ */
+ ANY,
+
+ /**
+ * BITAND flags == match.
+ */
+ AND
+}
diff --git a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java
index 4725d41e5..14ab457c8 100644
--- a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java
+++ b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java
@@ -136,6 +136,21 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return new ArrayIsEmptyExpression(propertyName, false);
}
+ @Override
+ public Expression bitwiseAny(String propertyName, long flags) {
+ return new BitwiseExpression(propertyName, BitwiseOp.ANY, flags, "!=", 0L);
+ }
+
+ @Override
+ public Expression bitwiseAll(String propertyName, long flags) {
+ return new BitwiseExpression(propertyName, BitwiseOp.ALL, flags, "=", flags);
+ }
+
+ @Override
+ public Expression bitwiseAnd(String propertyName, long flags, long match) {
+ return new BitwiseExpression(propertyName, BitwiseOp.AND, flags, "=", match);
+ }
+
/**
* Equal To - property equal to the given value.
*/
diff --git a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java
index 29747b439..ef2e8c89c 100644
--- a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java
+++ b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java
@@ -699,6 +699,24 @@ public class DefaultExpressionList implements SpiExpressionList {
return this;
}
+ @Override
+ public ExpressionList bitwiseAny(String propertyName, long flags) {
+ add(expr.bitwiseAny(propertyName, flags));
+ return this;
+ }
+
+ @Override
+ public ExpressionList bitwiseAll(String propertyName, long flags) {
+ add(expr.bitwiseAll(propertyName, flags));
+ return this;
+ }
+
+ @Override
+ public ExpressionList bitwiseAnd(String propertyName, long flags, long match) {
+ add(expr.bitwiseAnd(propertyName, flags, match));
+ return this;
+ }
+
@Override
public ExpressionList eq(String propertyName, Object value) {
add(expr.eq(propertyName, value));
diff --git a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java
index a1cc868f0..557c53996 100644
--- a/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java
+++ b/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionRequest.java
@@ -2,10 +2,10 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.SpiExpressionList;
import io.ebeaninternal.api.SpiExpressionRequest;
-import io.ebeaninternal.server.core.DbExpressionHandler;
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.DeployParser;
+import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
import io.ebeaninternal.server.persist.Binder;
import io.ebeaninternal.server.type.DataBind;
diff --git a/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java b/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java
index 4d4c3a53c..d7d6c0c7a 100644
--- a/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java
@@ -533,6 +533,21 @@ class JunctionExpression implements SpiJunction, SpiExpression, Expression
return exprList.arrayIsNotEmpty(propertyName);
}
+ @Override
+ public ExpressionList bitwiseAny(String propertyName, long flags) {
+ return exprList.bitwiseAny(propertyName, flags);
+ }
+
+ @Override
+ public ExpressionList bitwiseAll(String propertyName, long flags) {
+ return exprList.bitwiseAll(propertyName, flags);
+ }
+
+ @Override
+ public ExpressionList bitwiseAnd(String propertyName, long flags, long match) {
+ return exprList.bitwiseAnd(propertyName, flags, match);
+ }
+
@Override
public ExpressionList ge(String propertyName, Object value) {
return exprList.ge(propertyName, value);
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java
new file mode 100644
index 000000000..584215d4c
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/BaseDbExpression.java
@@ -0,0 +1,60 @@
+package io.ebeaninternal.server.expression.platform;
+
+import io.ebeaninternal.api.SpiExpressionRequest;
+import io.ebeaninternal.server.expression.BitwiseOp;
+
+/**
+ * Not supported JSON or ARRAY expression handler.
+ */
+abstract class BaseDbExpression implements DbExpressionHandler {
+
+ private final String concatOperator;
+
+ BaseDbExpression(String concatOperator) {
+ this.concatOperator = concatOperator;
+ }
+
+ @Override
+ public String getConcatOperator() {
+ return concatOperator;
+ }
+
+ @Override
+ public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
+
+ String bitOp = bitOp(operator);
+ request.append("(").append(propName).append(" ").append(bitOp).append(" ? ").append(compare).append(" ?)");
+ }
+
+ private String bitOp(BitwiseOp operator) {
+ switch (operator) {
+ case ANY:
+ case AND:
+ case ALL:
+ return "&";
+ default:
+ throw new IllegalArgumentException("Unknown Bitwise operator " + operator + " not handled?");
+ }
+ }
+
+ /**
+ * Common alternative where the bitwise operation is a function (specifically bitand is used - H2 and Oracle).
+ */
+ protected void bitwiseFunction(SpiExpressionRequest request, String propName, BitwiseOp operator, String compare) {
+
+ String funcName = functionName(operator);
+ request.append(funcName).append("(").append(propName).append(", ?) ").append(compare).append(" ?");
+ }
+
+ protected String functionName(BitwiseOp operator) {
+ switch (operator) {
+ case AND:
+ case ANY:
+ case ALL:
+ return "bitand";
+ default:
+ throw new IllegalArgumentException("Unknown Bitwise operator " + operator + " not handled?");
+ }
+ }
+
+}
diff --git a/src/main/java/io/ebeaninternal/server/core/BasicDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/BasicDbExpression.java
similarity index 94%
rename from src/main/java/io/ebeaninternal/server/core/BasicDbExpression.java
rename to src/main/java/io/ebeaninternal/server/expression/platform/BasicDbExpression.java
index ef8ad5b4a..adacca04d 100644
--- a/src/main/java/io/ebeaninternal/server/core/BasicDbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/BasicDbExpression.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.core;
+package io.ebeaninternal.server.expression.platform;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.expression.Op;
diff --git a/src/main/java/io/ebeaninternal/server/core/DbExpressionHandler.java b/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandler.java
similarity index 73%
rename from src/main/java/io/ebeaninternal/server/core/DbExpressionHandler.java
rename to src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandler.java
index 7ce5a4074..7cf6d696a 100644
--- a/src/main/java/io/ebeaninternal/server/core/DbExpressionHandler.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandler.java
@@ -1,6 +1,7 @@
-package io.ebeaninternal.server.core;
+package io.ebeaninternal.server.expression.platform;
import io.ebeaninternal.api.SpiExpressionRequest;
+import io.ebeaninternal.server.expression.BitwiseOp;
import io.ebeaninternal.server.expression.Op;
/**
@@ -28,4 +29,8 @@ public interface DbExpressionHandler {
*/
void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty);
+ /**
+ * Add the bitwise expression.
+ */
+ void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match);
}
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandlerFactory.java b/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandlerFactory.java
new file mode 100644
index 000000000..b7b62eb71
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/DbExpressionHandlerFactory.java
@@ -0,0 +1,31 @@
+package io.ebeaninternal.server.expression.platform;
+
+import io.ebean.annotation.Platform;
+import io.ebean.config.dbplatform.DatabasePlatform;
+
+
+public class DbExpressionHandlerFactory {
+
+ /**
+ * Create and return the appropriate platform specific handing of expressions.
+ */
+ public static DbExpressionHandler from(DatabasePlatform databasePlatform) {
+
+ Platform platform = databasePlatform.getPlatform();
+ String concatOperator = databasePlatform.getConcatOperator();
+ switch (platform) {
+ case H2:
+ return new H2DbExpression(concatOperator);
+ case POSTGRES:
+ return new PostgresDbExpression(concatOperator);
+ case MYSQL:
+ return new MySqlDbExpression(concatOperator);
+ case ORACLE:
+ return new OracleDbExpression(concatOperator);
+ case SQLSERVER:
+ return new SqlServerDbExpression(concatOperator);
+ default:
+ return new BasicDbExpression(concatOperator);
+ }
+ }
+}
diff --git a/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java
new file mode 100644
index 000000000..4e0b544f2
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/H2DbExpression.java
@@ -0,0 +1,20 @@
+package io.ebeaninternal.server.expression.platform;
+
+import io.ebeaninternal.api.SpiExpressionRequest;
+import io.ebeaninternal.server.expression.BitwiseOp;
+
+/**
+ * H2 handling of platform specific expressions.
+ */
+class H2DbExpression extends BasicDbExpression {
+
+ H2DbExpression(String concatOperator) {
+ super(concatOperator);
+ }
+
+ @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/MySqlDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/MySqlDbExpression.java
new file mode 100644
index 000000000..e0e04ad1f
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/MySqlDbExpression.java
@@ -0,0 +1,12 @@
+package io.ebeaninternal.server.expression.platform;
+
+/**
+ * MySql specific handling of platform specific expressions.
+ */
+class MySqlDbExpression extends BasicDbExpression {
+
+ MySqlDbExpression(String concatOperator) {
+ super(concatOperator);
+ }
+
+}
diff --git a/src/main/java/io/ebeaninternal/server/core/OracleDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java
similarity index 75%
rename from src/main/java/io/ebeaninternal/server/core/OracleDbExpression.java
rename to src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java
index 82480723d..4347d2e80 100644
--- a/src/main/java/io/ebeaninternal/server/core/OracleDbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/OracleDbExpression.java
@@ -1,10 +1,11 @@
-package io.ebeaninternal.server.core;
+package io.ebeaninternal.server.expression.platform;
import io.ebeaninternal.api.SpiExpressionRequest;
+import io.ebeaninternal.server.expression.BitwiseOp;
import io.ebeaninternal.server.expression.Op;
/**
- * Oracle JSON expression handler, ARRAY expressions not supported.
+ * Oracle handling of platform specific expressions. ARRAY expressions not supported.
*/
public class OracleDbExpression extends BaseDbExpression {
@@ -25,6 +26,11 @@ public class OracleDbExpression extends BaseDbExpression {
}
}
+ @Override
+ public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
+ bitwiseFunction(request, propName, operator, compare);
+ }
+
@Override
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
throw new IllegalStateException("ARRAY expressions not supported on Oracle");
diff --git a/src/main/java/io/ebeaninternal/server/core/PostgresCast.java b/src/main/java/io/ebeaninternal/server/expression/platform/PostgresCast.java
similarity index 95%
rename from src/main/java/io/ebeaninternal/server/core/PostgresCast.java
rename to src/main/java/io/ebeaninternal/server/expression/platform/PostgresCast.java
index 47dbb3f74..3e833cb12 100644
--- a/src/main/java/io/ebeaninternal/server/core/PostgresCast.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/PostgresCast.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.core;
+package io.ebeaninternal.server.expression.platform;
/**
* Helper for determining type casting for JSON and ARRAY expressions.
diff --git a/src/main/java/io/ebeaninternal/server/core/PostgresDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java
similarity index 97%
rename from src/main/java/io/ebeaninternal/server/core/PostgresDbExpression.java
rename to src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java
index a6f42bc68..4af9aa2f7 100644
--- a/src/main/java/io/ebeaninternal/server/core/PostgresDbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/PostgresDbExpression.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.core;
+package io.ebeaninternal.server.expression.platform;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.expression.Op;
diff --git a/src/main/java/io/ebeaninternal/server/core/SqlServerDbExpression.java b/src/main/java/io/ebeaninternal/server/expression/platform/SqlServerDbExpression.java
similarity index 95%
rename from src/main/java/io/ebeaninternal/server/core/SqlServerDbExpression.java
rename to src/main/java/io/ebeaninternal/server/expression/platform/SqlServerDbExpression.java
index 06a7824a1..dc52066e3 100644
--- a/src/main/java/io/ebeaninternal/server/core/SqlServerDbExpression.java
+++ b/src/main/java/io/ebeaninternal/server/expression/platform/SqlServerDbExpression.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.core;
+package io.ebeaninternal.server.expression.platform;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.expression.Op;
diff --git a/src/main/java/io/ebeaninternal/server/persist/Binder.java b/src/main/java/io/ebeaninternal/server/persist/Binder.java
index 7a69ee7eb..55833eae5 100644
--- a/src/main/java/io/ebeaninternal/server/persist/Binder.java
+++ b/src/main/java/io/ebeaninternal/server/persist/Binder.java
@@ -2,9 +2,9 @@ package io.ebeaninternal.server.persist;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebeaninternal.api.BindParams;
-import io.ebeaninternal.server.core.DbExpressionHandler;
import io.ebeaninternal.server.core.Message;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
+import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
import io.ebeaninternal.server.persist.platform.MultiValueBind;
import io.ebeaninternal.server.transaction.TransactionManager;
import io.ebeaninternal.server.type.DataBind;
diff --git a/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java b/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java
index f0179ea0a..5bd44e3de 100644
--- a/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java
+++ b/src/test/java/io/ebeaninternal/server/expression/TDSpiExpressionRequest.java
@@ -1,9 +1,9 @@
package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.SpiExpressionRequest;
-import io.ebeaninternal.server.core.DbExpressionHandler;
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;
+import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/test/java/io/ebeaninternal/server/core/PostgresCastTest.java b/src/test/java/io/ebeaninternal/server/expression/platform/PostgresCastTest.java
similarity index 84%
rename from src/test/java/io/ebeaninternal/server/core/PostgresCastTest.java
rename to src/test/java/io/ebeaninternal/server/expression/platform/PostgresCastTest.java
index f8e43263f..526ca3353 100644
--- a/src/test/java/io/ebeaninternal/server/core/PostgresCastTest.java
+++ b/src/test/java/io/ebeaninternal/server/expression/platform/PostgresCastTest.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.core;
+package io.ebeaninternal.server.expression.platform;
import org.junit.Test;
@@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class PostgresCastTest {
@Test
- public void cast() throws Exception {
+ public void cast() {
assertThat(PostgresCast.cast(1)).isEqualTo("::integer");
assertThat(PostgresCast.cast(1L)).isEqualTo("::bigint");
@@ -17,7 +17,7 @@ public class PostgresCastTest {
}
@Test
- public void cast1() throws Exception {
+ public void cast1() {
assertThat(PostgresCast.cast(1, true)).isEqualTo("::integer[]");
assertThat(PostgresCast.cast(1L, true)).isEqualTo("::bigint[]");
diff --git a/src/test/java/org/tests/expression/bitwise/BwBean.java b/src/test/java/org/tests/expression/bitwise/BwBean.java
new file mode 100644
index 000000000..5c7fab206
--- /dev/null
+++ b/src/test/java/org/tests/expression/bitwise/BwBean.java
@@ -0,0 +1,70 @@
+package org.tests.expression.bitwise;
+
+import io.ebean.Model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Version;
+
+@Entity
+public class BwBean extends Model {
+
+ @Id
+ long id;
+
+ String name;
+
+ // sqlserver wants integer type for bitwise AND operator
+ @Column(columnDefinition = "integer")
+ long flags;
+
+ @Version
+ long version;
+
+ public BwBean(String name) {
+ this.name = name;
+ }
+
+ public BwBean(String name, long flags) {
+ this.name = name;
+ this.flags = flags;
+ }
+
+ @Override
+ public String toString() {
+ return "nm:" + name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getFlags() {
+ return flags;
+ }
+
+ public void setFlags(long flags) {
+ this.flags = flags;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+
+ public void setVersion(long version) {
+ this.version = version;
+ }
+}
diff --git a/src/test/java/org/tests/expression/bitwise/BwFlags.java b/src/test/java/org/tests/expression/bitwise/BwFlags.java
new file mode 100644
index 000000000..41944659d
--- /dev/null
+++ b/src/test/java/org/tests/expression/bitwise/BwFlags.java
@@ -0,0 +1,78 @@
+package org.tests.expression.bitwise;
+
+public class BwFlags {
+
+ public static final int NOTHING = 0;
+
+ /**
+ * Indicates the bean is being inserted.
+ */
+ public static final int HAS_COLOUR = 0x00000001;
+
+ /**
+ * Indicates persist cascade.
+ */
+ public static final int HAS_SIZE = 0x00000002;
+
+ /**
+ * Indicates Publish mode.
+ */
+ public static final int HAS_BULK = 0x00000004;
+
+ /**
+ * Return true if part of a Merge or Publish.
+ */
+ public static boolean isColour(long state) {
+ return (state & HAS_COLOUR) != 0;
+ }
+
+ /**
+ * Return true if the given flag is set.
+ */
+ public static boolean isSet(int state, int flag) {
+ return (state & flag) == flag;
+ }
+
+ public static int setHasColour(int state) {
+ return set(state, HAS_COLOUR, true);
+ }
+
+ /**
+ * Parent was not inserted.
+ */
+ public static int unsetHasColour(int state) {
+ return set(state, HAS_COLOUR, false);
+ }
+
+ /**
+ * Set Recurse flag.
+ */
+ public static int setHasSize(int state) {
+ return set(state, HAS_SIZE, true);
+ }
+
+ public static int unsetHasSize(int state) {
+ return set(state, HAS_SIZE, false);
+ }
+
+ /**
+ * Set Publish flag.
+ */
+ public static int setHasBulk(int state) {
+ return set(state, HAS_BULK, true);
+ }
+
+ public static int unsetHasBulk(int state) {
+ return set(state, HAS_BULK, false);
+ }
+
+
+ private static int set(int state, int flag, boolean setFlag) {
+ if (setFlag) {
+ return (state |= flag);
+ } else {
+ return state &= ~flag;
+ }
+ }
+
+}
diff --git a/src/test/java/org/tests/expression/bitwise/TestBitwiseExpressions.java b/src/test/java/org/tests/expression/bitwise/TestBitwiseExpressions.java
new file mode 100644
index 000000000..05be5d1ae
--- /dev/null
+++ b/src/test/java/org/tests/expression/bitwise/TestBitwiseExpressions.java
@@ -0,0 +1,141 @@
+package org.tests.expression.bitwise;
+
+import io.ebean.BaseTestCase;
+import io.ebean.Ebean;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class TestBitwiseExpressions extends BaseTestCase {
+
+ @Test
+ public void where() {
+
+ setup();
+ bitwiseAnd();
+ bitwiseAny();
+ bitwiseAll();
+ }
+
+ private void bitwiseAnd() {
+
+ List list = Ebean.find(BwBean.class)
+ // not bulk set AND size set
+ .where().bitwiseAnd("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE, BwFlags.HAS_SIZE)
+ .findList();
+
+ assertThat(list).hasSize(1);
+ assertThat(list.get(0).getName()).isEqualTo("SizeOnly");
+
+ list = Ebean.find(BwBean.class)
+ // bulk set AND not size set
+ .where().bitwiseAnd("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE, BwFlags.HAS_BULK)
+ .findList();
+
+ assertThat(list).hasSize(1);
+ assertThat(list.get(0).getName()).isEqualTo("ColourAndBulk");
+
+ list = Ebean.find(BwBean.class)
+ // bulk set AND not size set
+ .where().bitwiseAnd("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR, BwFlags.HAS_COLOUR)
+ .findList();
+
+ assertThat(list).hasSize(1);
+ assertThat(list.get(0).getName()).isEqualTo("ColourOnly");
+ }
+
+ private void bitwiseAny() {
+
+ List list = Ebean.find(BwBean.class)
+ .where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE)
+ .findList();
+
+ assertThat(list).hasSize(3);
+ assertThat(list.get(0).getName()).isEqualTo("SizeOnly");
+ assertThat(list.get(1).getName()).isEqualTo("ColourAndBulk");
+ assertThat(list.get(2).getName()).isEqualTo("Everything");
+
+
+ list = Ebean.find(BwBean.class)
+ .where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE + BwFlags.HAS_COLOUR)
+ .findList();
+
+ assertThat(list).hasSize(4);
+
+ list = Ebean.find(BwBean.class)
+ .where().bitwiseAny("flags", BwFlags.HAS_SIZE + BwFlags.HAS_COLOUR)
+ .findList();
+
+ assertThat(list).hasSize(4);
+
+ list = Ebean.find(BwBean.class)
+ .where().bitwiseAny("flags", BwFlags.HAS_SIZE)
+ .findList();
+
+ assertThat(list).hasSize(2);
+ assertThat(list.get(0).getName()).isEqualTo("SizeOnly");
+ assertThat(list.get(1).getName()).isEqualTo("Everything");
+
+ list = Ebean.find(BwBean.class)
+ .where().bitwiseAny("flags", BwFlags.HAS_COLOUR)
+ .findList();
+
+ assertThat(list).hasSize(3);
+ assertThat(list.get(0).getName()).isEqualTo("ColourOnly");
+ assertThat(list.get(1).getName()).isEqualTo("ColourAndBulk");
+ assertThat(list.get(2).getName()).isEqualTo("Everything");
+ }
+
+ private void bitwiseAll() {
+
+ List list = Ebean.find(BwBean.class)
+ .where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE)
+ .findList();
+
+ assertThat(list).hasSize(1);
+ assertThat(list.get(0).getName()).isEqualTo("Everything");
+
+ list = Ebean.find(BwBean.class)
+ .where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
+ .orderBy().asc("id")
+ .findList();
+
+ assertThat(list).hasSize(2);
+ assertThat(list.get(0).getName()).isEqualTo("ColourAndBulk");
+ assertThat(list.get(1).getName()).isEqualTo("Everything");
+
+ list = Ebean.find(BwBean.class)
+ .where().bitwiseAll("flags", BwFlags.HAS_SIZE)
+ .orderBy().asc("id")
+ .findList();
+
+ assertThat(list).hasSize(2);
+ assertThat(list.get(0).getName()).isEqualTo("SizeOnly");
+ assertThat(list.get(1).getName()).isEqualTo("Everything");
+
+ list = Ebean.find(BwBean.class)
+ .where().bitwiseAll("flags", BwFlags.HAS_COLOUR)
+ .orderBy().asc("id")
+ .findList();
+
+ assertThat(list).hasSize(3);
+ assertThat(list.get(0).getName()).isEqualTo("ColourOnly");
+ assertThat(list.get(1).getName()).isEqualTo("ColourAndBulk");
+ assertThat(list.get(2).getName()).isEqualTo("Everything");
+
+ }
+
+ private void setup() {
+
+ Ebean.find(BwBean.class).delete();
+
+ new BwBean("Nothing", BwFlags.NOTHING).save();
+ new BwBean("ColourOnly", BwFlags.HAS_COLOUR).save();
+ new BwBean("SizeOnly", BwFlags.HAS_SIZE).save();
+ new BwBean("ColourAndBulk", BwFlags.HAS_COLOUR + BwFlags.HAS_BULK).save();
+ new BwBean("Everything", BwFlags.HAS_COLOUR + BwFlags.HAS_BULK + BwFlags.HAS_SIZE).save();
+
+ }
+}
diff --git a/src/test/java/org/tests/repository/CustomerRepository.java b/src/test/java/org/tests/repository/CustomerRepository.java
index 31d18ef96..1dfdb51b1 100644
--- a/src/test/java/org/tests/repository/CustomerRepository.java
+++ b/src/test/java/org/tests/repository/CustomerRepository.java
@@ -4,12 +4,13 @@ import io.ebean.BeanRepository;
import io.ebean.EbeanServer;
import org.tests.model.basic.Customer;
-import javax.inject.Inject;
import java.util.List;
+//import javax.inject.Inject;
+
public class CustomerRepository extends BeanRepository {
- @Inject
+ //@Inject
public CustomerRepository(EbeanServer server) {
super(Customer.class, server);
}