Skip to content

Commit e0e27a3

Browse files
committed
Port stringOrderCollation to QueryBuilder.
- Though change signature to accept only new StringOrder constant instead of any SQLite collate string. Support setParameter in daocompat, properly rebuild query. - Support setParameter and undeprecate it. - The ObjectBox query is now (re)built when creating a new query or resetting it (for a new thread). QueryBuilder now only records desired conditions and orders. Previously would simply re-use the same ObjectBox query object built by QueryBuilder, which would obviously not be re-set to initial values. JNI/Java: setParameter for FP, between for FP Support double values for setParameter. - Also throw on unsupported parameter types. Support double values for BETWEEN op. - Add test. add :tests:test-proguard
1 parent 81eec62 commit e0e27a3

10 files changed

Lines changed: 503 additions & 10 deletions

File tree

objectbox-java/src/main/java/io/objectbox/query/Query.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public class Query<T> {
5050
private native static void nativeSetParameters(long handle, int propertyId, String parameterAlias, long value1,
5151
long value2);
5252

53+
private native static void nativeSetParameter(long handle, int propertyId, String parameterAlias, double value);
54+
55+
private native static void nativeSetParameters(long handle, int propertyId, String parameterAlias, double value1,
56+
double value2);
57+
5358
private final Box<T> box;
5459
private final long handle;
5560

@@ -131,6 +136,13 @@ public void setParameter(Property property, long value) {
131136
nativeSetParameter(handle, property.getId(), null, value);
132137
}
133138

139+
public void setParameter(Property property, double value) {
140+
nativeSetParameter(handle, property.getId(), null, value);
141+
}
142+
143+
/**
144+
* @throws NullPointerException if given date is null
145+
*/
134146
public void setParameter(Property property, Date value) {
135147
setParameter(property, value.getTime());
136148
}
@@ -139,6 +151,10 @@ public void setParameters(Property property, long value1, long value2) {
139151
nativeSetParameters(handle, property.getId(), null, value1, value2);
140152
}
141153

154+
public void setParameters(Property property, double value1, double value2) {
155+
nativeSetParameters(handle, property.getId(), null, value1, value2);
156+
}
157+
142158
public long remove() {
143159
return box.internalCallWithWriterHandle(new CallWithHandle<Long>() {
144160
@Override

objectbox-java/src/main/java/io/objectbox/query/QueryBuilder.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public enum StringOrder {
106106

107107
private static native long nativeGreater(long handle, int propertyId, double value);
108108

109+
private static native long nativeBetween(long handle, int propertyId, double value1, double value2);
109110

110111
@Internal
111112
public QueryBuilder(Box<T> box, long storeHandle, String entityName) {
@@ -285,7 +286,6 @@ public QueryBuilder<T> endsWith(Property property, String value, StringOrder ord
285286
return this;
286287
}
287288

288-
289289
public QueryBuilder<T> less(Property property, double value) {
290290
nativeLess(handle, property.getId(), value);
291291
return this;
@@ -296,4 +296,9 @@ public QueryBuilder<T> greater(Property property, double value) {
296296
return this;
297297
}
298298

299+
public QueryBuilder<T> between(Property property, double value1, double value2) {
300+
nativeBetween(handle, property.getId(), value1, value2);
301+
return this;
302+
}
303+
299304
}

objectbox-java/src/main/java/io/objectbox/query/QueryCondition.java

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.objectbox.annotation.apihint.Experimental;
2222
import io.objectbox.annotation.apihint.Internal;
2323
import io.objectbox.exception.DbException;
24+
import io.objectbox.query.QueryBuilder.StringOrder;
2425

2526
/**
2627
* Internal interface to model WHERE conditions used in queries. Use the {@link Property} objects in the DAO classes to
@@ -30,7 +31,11 @@
3031
@Internal
3132
public interface QueryCondition {
3233

33-
void applyTo(QueryBuilder queryBuilder);
34+
void applyTo(QueryBuilder queryBuilder, StringOrder stringOrder);
35+
36+
void setParameterFor(Query query, Object parameter);
37+
38+
void setParameterFor(Query query, Object parameter1, Object parameter2);
3439

3540
abstract class AbstractCondition implements QueryCondition {
3641

@@ -80,28 +85,32 @@ public PropertyCondition(Property property, Operation operation, Object[] values
8085
this.operation = operation;
8186
}
8287

83-
public void applyTo(QueryBuilder queryBuilder) {
88+
public void applyTo(QueryBuilder queryBuilder, StringOrder stringOrder) {
8489
if (operation == Operation.EQUALS) {
8590
if (value instanceof Long) {
8691
queryBuilder.equal(property, (Long) value);
8792
} else if (value instanceof Integer) {
8893
queryBuilder.equal(property, (Integer) value);
8994
} else if (value instanceof String) {
90-
queryBuilder.equal(property, (String) value);
95+
queryBuilder.equal(property, (String) value, stringOrder);
9196
}
9297
} else if (operation == Operation.NOT_EQUALS) {
9398
if (value instanceof Long) {
9499
queryBuilder.notEqual(property, (Long) value);
95100
} else if (value instanceof Integer) {
96101
queryBuilder.notEqual(property, (Integer) value);
97102
} else if (value instanceof String) {
98-
queryBuilder.notEqual(property, (String) value);
103+
queryBuilder.notEqual(property, (String) value, stringOrder);
99104
}
100105
} else if (operation == Operation.BETWEEN) {
101106
if (values[0] instanceof Long && values[1] instanceof Long) {
102107
queryBuilder.between(property, (Long) values[0], (Long) values[1]);
103108
} else if (values[0] instanceof Integer && values[1] instanceof Integer) {
104109
queryBuilder.between(property, (Integer) values[0], (Integer) values[1]);
110+
} else if (values[0] instanceof Double && values[1] instanceof Double) {
111+
queryBuilder.between(property, (Double) values[0], (Double) values[1]);
112+
} else if (values[0] instanceof Float && values[1] instanceof Float) {
113+
queryBuilder.between(property, (Float) values[0], (Float) values[1]);
105114
}
106115
} else if (operation == Operation.IN) {
107116
// just check the first value and assume all others are of the same type
@@ -145,13 +154,13 @@ public void applyTo(QueryBuilder queryBuilder) {
145154
queryBuilder.notNull(property);
146155
} else if (operation == Operation.CONTAINS) {
147156
// no need for greenDAO compat, so only String was allowed
148-
queryBuilder.contains(property, (String) value);
157+
queryBuilder.contains(property, (String) value, stringOrder);
149158
} else if (operation == Operation.STARTS_WITH) {
150159
// no need for greenDAO compat, so only String was allowed
151-
queryBuilder.startsWith(property, (String) value);
160+
queryBuilder.startsWith(property, (String) value, stringOrder);
152161
} else if (operation == Operation.ENDS_WITH) {
153162
// no need for greenDAO compat, so only String was allowed
154-
queryBuilder.endsWith(property, (String) value);
163+
queryBuilder.endsWith(property, (String) value, stringOrder);
155164
} else {
156165
throw new UnsupportedOperationException("This operation is not known.");
157166
}
@@ -208,6 +217,52 @@ private static Object[] checkValuesForType(Property property, Operation operatio
208217
return values;
209218
}
210219

220+
@Override
221+
public void setParameterFor(Query query, Object parameter) {
222+
if (parameter == null) {
223+
throw new IllegalArgumentException("The new parameter can not be null.");
224+
}
225+
if (operation == Operation.BETWEEN) {
226+
throw new UnsupportedOperationException("The BETWEEN condition requires two parameters.");
227+
}
228+
if (operation == Operation.IN) {
229+
throw new UnsupportedOperationException("The IN condition does not support changing parameters.");
230+
}
231+
if (parameter instanceof Long) {
232+
query.setParameter(property, (Long) parameter);
233+
} else if (parameter instanceof Integer) {
234+
query.setParameter(property, (Integer) parameter);
235+
} else if (parameter instanceof String) {
236+
query.setParameter(property, (String) parameter);
237+
} else if (parameter instanceof Double) {
238+
query.setParameter(property, (Double) parameter);
239+
} else if (parameter instanceof Float) {
240+
query.setParameter(property, (Float) parameter);
241+
} else {
242+
throw new IllegalArgumentException("Only LONG, INTEGER, DOUBLE, FLOAT or STRING parameters are supported.");
243+
}
244+
}
245+
246+
@Override
247+
public void setParameterFor(Query query, Object parameter1, Object parameter2) {
248+
if (parameter1 == null || parameter2 == null) {
249+
throw new IllegalArgumentException("The new parameters can not be null.");
250+
}
251+
if (operation != Operation.BETWEEN) {
252+
throw new UnsupportedOperationException("Only the BETWEEN condition supports two parameters.");
253+
}
254+
if (parameter1 instanceof Long && parameter2 instanceof Long) {
255+
query.setParameters(property, (Long) parameter1, (Long) parameter2);
256+
} else if (parameter1 instanceof Integer && parameter2 instanceof Integer) {
257+
query.setParameters(property, (Integer) parameter1, (Integer) parameter2);
258+
} else if (parameter1 instanceof Double && parameter2 instanceof Double) {
259+
query.setParameters(property, (Double) parameter1, (Double) parameter2);
260+
} else if (parameter1 instanceof Float && parameter2 instanceof Float) {
261+
query.setParameters(property, (Float) parameter1, (Float) parameter2);
262+
} else {
263+
throw new IllegalArgumentException("The BETWEEN condition only supports LONG, INTEGER, DOUBLE or FLOAT parameters.");
264+
}
265+
}
211266
}
212267

213268
}

tests/objectbox-java-test/src/main/java/io/objectbox/QueryTest.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public void testFindKeysUnordered() {
222222
}
223223

224224
@Test
225-
public void testSetParameterScalar() {
225+
public void testSetParameterInt() {
226226
putTestEntitiesScalars();
227227
Query<TestEntity> query = box.query().equal(SimpleInt, 2007).build();
228228
assertEquals(8, query.findUnique().getId());
@@ -231,7 +231,7 @@ public void testSetParameterScalar() {
231231
}
232232

233233
@Test
234-
public void testSetParameter2Scalars() {
234+
public void testSetParameter2Ints() {
235235
putTestEntitiesScalars();
236236
Query<TestEntity> query = box.query().between(SimpleInt, 2005, 2008).build();
237237
assertEquals(4, query.count());
@@ -242,6 +242,27 @@ public void testSetParameter2Scalars() {
242242
assertEquals(4, entities.get(1).getId());
243243
}
244244

245+
@Test
246+
public void testSetParameterFloat() {
247+
putTestEntitiesScalars();
248+
Query<TestEntity> query = box.query().greater(SimpleFloat, 20000.65).build();
249+
assertEquals(3, query.count());
250+
query.setParameter(SimpleFloat, 20000.75);
251+
assertEquals(2, query.count());
252+
}
253+
254+
@Test
255+
public void testSetParameter2Floats() {
256+
putTestEntitiesScalars();
257+
Query<TestEntity> query = box.query().between(SimpleFloat, 20000.15, 20000.75).build();
258+
assertEquals(6, query.count());
259+
query.setParameters(SimpleFloat, 20000.65, 20000.85);
260+
List<TestEntity> entities = query.find();
261+
assertEquals(2, entities.size());
262+
assertEquals(8, entities.get(0).getId());
263+
assertEquals(9, entities.get(1).getId());
264+
}
265+
245266
@Test
246267
public void testSetParameterString() {
247268
putTestEntitiesStrings();
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# This is a configuration file for ProGuard.
2+
# http://proguard.sourceforge.net/index.html#manual/usage.html
3+
4+
# Optimizations: If you don't want to optimize, use the
5+
# proguard-android.txt configuration file instead of this one, which
6+
# turns off the optimization flags. Adding optimization introduces
7+
# certain risks, since for example not all optimizations performed by
8+
# ProGuard works on all versions of Dalvik. The following flags turn
9+
# off various optimizations known to have issues, but the list may not
10+
# be complete or up to date. (The "arithmetic" optimization can be
11+
# used if you are only targeting Android 2.0 or later.) Make sure you
12+
# test thoroughly if you go this route.
13+
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
14+
-optimizationpasses 5
15+
-allowaccessmodification
16+
-dontpreverify
17+
18+
# The remainder of this file is identical to the non-optimized version
19+
# of the Proguard configuration file (except that the other file has
20+
# flags to turn off optimization).
21+
22+
-dontusemixedcaseclassnames
23+
-dontskipnonpubliclibraryclasses
24+
-verbose
25+
26+
-keepattributes *Annotation*
27+
-keep public class com.google.vending.licensing.ILicensingService
28+
-keep public class com.android.vending.licensing.ILicensingService
29+
30+
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
31+
-keepclasseswithmembernames class * {
32+
native <methods>;
33+
}
34+
35+
# keep setters in Views so that animations can still work.
36+
# see http://proguard.sourceforge.net/manual/examples.html#beans
37+
-keepclassmembers public class * extends android.view.View {
38+
void set*(***);
39+
*** get*();
40+
}
41+
42+
# We want to keep methods in Activity that could be used in the XML attribute onClick
43+
-keepclassmembers class * extends android.app.Activity {
44+
public void *(android.view.View);
45+
}
46+
47+
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
48+
-keepclassmembers enum * {
49+
public static **[] values();
50+
public static ** valueOf(java.lang.String);
51+
}
52+
53+
-keepclassmembers class * implements android.os.Parcelable {
54+
public static final android.os.Parcelable$Creator CREATOR;
55+
}
56+
57+
-keepclassmembers class **.R$* {
58+
public static <fields>;
59+
}
60+
61+
# The support library contains references to newer platform versions.
62+
# Don't warn about those in case this app is linking against an older
63+
# platform version. We know about them, and they are safe.
64+
-dontwarn android.support.**
65+
66+
# Understand the @Keep support annotation.
67+
-keep class android.support.annotation.Keep
68+
69+
-keep @android.support.annotation.Keep class * {*;}
70+
71+
-keepclasseswithmembers class * {
72+
@android.support.annotation.Keep <methods>;
73+
}
74+
75+
-keepclasseswithmembers class * {
76+
@android.support.annotation.Keep <fields>;
77+
}
78+
79+
-keepclasseswithmembers class * {
80+
@android.support.annotation.Keep <init>(...);
81+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.objectbox.test.proguard;
2+
3+
import io.objectbox.BoxStore;
4+
import io.objectbox.BoxStoreBuilder;
5+
import io.objectbox.ModelBuilder;
6+
import io.objectbox.ModelBuilder.EntityBuilder;
7+
import io.objectbox.model.PropertyFlags;
8+
import io.objectbox.model.PropertyType;
9+
10+
11+
// THIS CODE IS GENERATED BY ObjectBox, DO NOT EDIT.
12+
/**
13+
* Starting point for working with your ObjectBox. All boxes are set up for your objects here.
14+
* <p>
15+
* First steps (Android): get a builder using {@link #builder()}, call {@link BoxStoreBuilder#androidContext(Object)},
16+
* and {@link BoxStoreBuilder#build()} to get a {@link BoxStore} to work with.
17+
*/
18+
public class MyObjectBox {
19+
20+
public static BoxStoreBuilder builder() {
21+
BoxStoreBuilder builder = new BoxStoreBuilder(getModel());
22+
builder.entity("ObfuscatedEntity", ObfuscatedEntity.class, ObfuscatedEntityCursor.class, new ObfuscatedEntity_());
23+
return builder;
24+
}
25+
26+
private static byte[] getModel() {
27+
ModelBuilder modelBuilder = new ModelBuilder();
28+
29+
EntityBuilder entityBuilder;
30+
31+
entityBuilder = modelBuilder.entity("ObfuscatedEntity");
32+
entityBuilder.property("id", PropertyType.Long)
33+
.flags(PropertyFlags.ID);
34+
entityBuilder.property("myInt", PropertyType.Int);
35+
entityBuilder.property("myString", PropertyType.String);
36+
entityBuilder.entityDone();
37+
38+
return modelBuilder.build();
39+
}
40+
41+
}

0 commit comments

Comments
 (0)