Skip to content

Commit 6b67922

Browse files
String order: require on string conditions in QueryBuilder.
- Do not check type if contains is used internally.
1 parent cdc4174 commit 6b67922

File tree

7 files changed

+36
-132
lines changed

7 files changed

+36
-132
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,8 @@ void applyCondition(QueryBuilder<T> builder) {
325325
builder.lessOrEqual(property, value, order);
326326
break;
327327
case CONTAINS:
328-
builder.contains(property, value, order);
328+
// Note: contains used for String[] as well, so do not enforce String type here.
329+
builder.containsNoTypeCheck(property, value, order);
329330
break;
330331
case STARTS_WITH:
331332
builder.startsWith(property, value, order);

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

Lines changed: 12 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@
3838
*
3939
* <pre>
4040
* userBox.query()
41-
* .equal(User_.firstName, "Joe")
41+
* .equal(User_.firstName, "Joe", StringOrder.CASE_SENSITIVE)
4242
* .order(User_.lastName)
4343
* .build()
4444
* .find()
4545
* </pre>
4646
*
4747
* <p>
48-
* To add a condition use the appropriate method, for example {@link #equal(Property, String)} or
48+
* To add a condition use the appropriate method, for example {@link #equal(Property, String, StringOrder)} or
4949
* {@link #isNull(Property)}. To order results use {@link #order(Property)} and its related methods.
5050
* <p>
5151
* Use {@link #build()} to create a {@link Query} object, which is used to actually get the results.
@@ -70,10 +70,11 @@ public enum StringOrder {
7070
CASE_INSENSITIVE,
7171

7272
/**
73-
* Checks case of ASCII characters when macthing results,
73+
* Checks case of ASCII characters when matching results,
7474
* e.g. the condition "= example" only matches "example", but not "Example".
7575
* <p>
76-
* Use this if the property has an index.
76+
* Use this if the property has an {@link io.objectbox.annotation.Index @Index}
77+
* to dramatically increase the speed of looking-up results.
7778
*/
7879
CASE_SENSITIVE
7980
}
@@ -449,7 +450,7 @@ public QueryBuilder<T> eager(int limit, RelationInfo relationInfo, @Nullable Rel
449450

450451
/**
451452
* Sets a filter that executes on primary query results (returned from the db core) on a Java level.
452-
* For efficiency reasons, you should always prefer primary criteria like {@link #equal(Property, String)} if
453+
* For efficiency reasons, you should always prefer primary criteria like {@link #equal(Property, long)} if
453454
* possible.
454455
* A filter requires to instantiate full Java objects beforehand, which is less efficient.
455456
* <p>
@@ -733,30 +734,6 @@ public QueryBuilder<T> between(Property<T> property, Date value1, Date value2) {
733734

734735
/**
735736
* Creates an "equal ('=')" condition for this property.
736-
* <p>
737-
* Ignores case when matching results, e.g. {@code equal(prop, "example")} matches both "Example" and "example".
738-
* <p>
739-
* Use {@link #equal(Property, String, StringOrder) equal(prop, value, StringOrder.CASE_SENSITIVE)} to only match
740-
* if case is equal.
741-
* <p>
742-
* Note: Use a case sensitive condition to utilize an {@link io.objectbox.annotation.Index @Index}
743-
* on {@code property}, dramatically speeding up look-up of results.
744-
*/
745-
public QueryBuilder<T> equal(Property<T> property, String value) {
746-
verifyHandle();
747-
checkCombineCondition(nativeEqual(handle, property.getId(), value, false));
748-
return this;
749-
}
750-
751-
/**
752-
* Creates an "equal ('=')" condition for this property.
753-
* <p>
754-
* Set {@code order} to {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to only match
755-
* if case is equal. E.g. {@code equal(prop, "example", StringOrder.CASE_SENSITIVE)} only matches "example",
756-
* but not "Example".
757-
* <p>
758-
* Note: Use a case sensitive condition to utilize an {@link io.objectbox.annotation.Index @Index}
759-
* on {@code property}, dramatically speeding up look-up of results.
760737
*/
761738
public QueryBuilder<T> equal(Property<T> property, String value, StringOrder order) {
762739
verifyHandle();
@@ -766,30 +743,6 @@ public QueryBuilder<T> equal(Property<T> property, String value, StringOrder ord
766743

767744
/**
768745
* Creates a "not equal ('&lt;&gt;')" condition for this property.
769-
* <p>
770-
* Ignores case when matching results, e.g. {@code notEqual(prop, "example")} excludes both "Example" and "example".
771-
* <p>
772-
* Use {@link #notEqual(Property, String, StringOrder) notEqual(prop, value, StringOrder.CASE_SENSITIVE)} to only exclude
773-
* if case is equal.
774-
* <p>
775-
* Note: Use a case sensitive condition to utilize an {@link io.objectbox.annotation.Index @Index}
776-
* on {@code property}, dramatically speeding up look-up of results.
777-
*/
778-
public QueryBuilder<T> notEqual(Property<T> property, String value) {
779-
verifyHandle();
780-
checkCombineCondition(nativeNotEqual(handle, property.getId(), value, false));
781-
return this;
782-
}
783-
784-
/**
785-
* Creates a "not equal ('&lt;&gt;')" condition for this property.
786-
* <p>
787-
* Set {@code order} to {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to only exclude
788-
* if case is equal. E.g. {@code notEqual(prop, "example", StringOrder.CASE_SENSITIVE)} only excludes "example",
789-
* but not "Example".
790-
* <p>
791-
* Note: Use a case sensitive condition to utilize an {@link io.objectbox.annotation.Index @Index}
792-
* on {@code property}, dramatically speeding up look-up of results.
793746
*/
794747
public QueryBuilder<T> notEqual(Property<T> property, String value, StringOrder order) {
795748
verifyHandle();
@@ -798,56 +751,32 @@ public QueryBuilder<T> notEqual(Property<T> property, String value, StringOrder
798751
}
799752

800753
/**
801-
* Ignores case when matching results. Use the overload and pass
802-
* {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to specify that case should not be ignored.
754+
* Creates an contains condition.
803755
* <p>
804756
* Note: for a String array property, use {@link #containsElement} instead.
805757
*/
806-
public QueryBuilder<T> contains(Property<T> property, String value) {
758+
public QueryBuilder<T> contains(Property<T> property, String value, StringOrder order) {
807759
if (String[].class == property.type) {
808760
throw new UnsupportedOperationException("For String[] only containsElement() is supported at this time.");
809761
}
810-
verifyHandle();
811-
checkCombineCondition(nativeContains(handle, property.getId(), value, false));
762+
containsNoTypeCheck(property, value, order);
812763
return this;
813764
}
814765

815766
/**
816767
* For a String array property, matches if at least one element equals the given value.
817768
*/
818-
public QueryBuilder<T> containsElement(Property<T> property, String value) {
769+
public QueryBuilder<T> containsElement(Property<T> property, String value, StringOrder order) {
819770
if (String[].class != property.type) {
820771
throw new IllegalArgumentException("containsElement is only supported for String[] properties.");
821772
}
822-
verifyHandle();
823-
checkCombineCondition(nativeContains(handle, property.getId(), value, false));
773+
containsNoTypeCheck(property, value, order);
824774
return this;
825775
}
826776

827-
/**
828-
* Ignores case when matching results. Use the overload and pass
829-
* {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to specify that case should not be ignored.
830-
*/
831-
public QueryBuilder<T> startsWith(Property<T> property, String value) {
832-
verifyHandle();
833-
checkCombineCondition(nativeStartsWith(handle, property.getId(), value, false));
834-
return this;
835-
}
836-
837-
/**
838-
* Ignores case when matching results. Use the overload and pass
839-
* {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to specify that case should not be ignored.
840-
*/
841-
public QueryBuilder<T> endsWith(Property<T> property, String value) {
842-
verifyHandle();
843-
checkCombineCondition(nativeEndsWith(handle, property.getId(), value, false));
844-
return this;
845-
}
846-
847-
public QueryBuilder<T> contains(Property<T> property, String value, StringOrder order) {
777+
void containsNoTypeCheck(Property<T> property, String value, StringOrder order) {
848778
verifyHandle();
849779
checkCombineCondition(nativeContains(handle, property.getId(), value, order == StringOrder.CASE_SENSITIVE));
850-
return this;
851780
}
852781

853782
public QueryBuilder<T> startsWith(Property<T> property, String value, StringOrder order) {
@@ -862,14 +791,6 @@ public QueryBuilder<T> endsWith(Property<T> property, String value, StringOrder
862791
return this;
863792
}
864793

865-
/**
866-
* Ignores case when matching results. Use the overload and pass
867-
* {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to specify that case should not be ignored.
868-
*/
869-
public QueryBuilder<T> less(Property<T> property, String value) {
870-
return less(property, value, StringOrder.CASE_INSENSITIVE);
871-
}
872-
873794
public QueryBuilder<T> less(Property<T> property, String value, StringOrder order) {
874795
verifyHandle();
875796
checkCombineCondition(nativeLess(handle, property.getId(), value, order == StringOrder.CASE_SENSITIVE, false));
@@ -882,14 +803,6 @@ public QueryBuilder<T> lessOrEqual(Property<T> property, String value, StringOrd
882803
return this;
883804
}
884805

885-
/**
886-
* Ignores case when matching results. Use the overload and pass
887-
* {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to specify that case should not be ignored.
888-
*/
889-
public QueryBuilder<T> greater(Property<T> property, String value) {
890-
return greater(property, value, StringOrder.CASE_INSENSITIVE);
891-
}
892-
893806
public QueryBuilder<T> greater(Property<T> property, String value, StringOrder order) {
894807
verifyHandle();
895808
checkCombineCondition(nativeGreater(handle, property.getId(), value, order == StringOrder.CASE_SENSITIVE, false));
@@ -902,14 +815,6 @@ public QueryBuilder<T> greaterOrEqual(Property<T> property, String value, String
902815
return this;
903816
}
904817

905-
/**
906-
* Ignores case when matching results. Use the overload and pass
907-
* {@link StringOrder#CASE_SENSITIVE StringOrder.CASE_SENSITIVE} to specify that case should not be ignored.
908-
*/
909-
public QueryBuilder<T> in(Property<T> property, String[] values) {
910-
return in(property, values, StringOrder.CASE_INSENSITIVE);
911-
}
912-
913818
public QueryBuilder<T> in(Property<T> property, String[] values, StringOrder order) {
914819
verifyHandle();
915820
checkCombineCondition(nativeIn(handle, property.getId(), values, order == StringOrder.CASE_SENSITIVE));

objectbox-kotlin/src/main/kotlin/io/objectbox/kotlin/QueryBuilder.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ inline fun <reified T> QueryBuilder<T>.inValues(property: Property<T>, values: L
2828
inline fun <reified T> QueryBuilder<T>.inValues(property: Property<T>, values: IntArray): QueryBuilder<T> =
2929
`in`(property, values)
3030

31-
/** An alias for the "in" method, which is a reserved keyword in Kotlin. */
32-
inline fun <reified T> QueryBuilder<T>.inValues(property: Property<T>, values: Array<String>): QueryBuilder<T> =
33-
`in`(property, values)
34-
3531
/** An alias for the "in" method, which is a reserved keyword in Kotlin. */
3632
inline fun <reified T> QueryBuilder<T>.inValues(
3733
property: Property<T>, values: Array<String>,

tests/objectbox-java-test/src/test/java/io/objectbox/query/PropertyQueryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public void testFindStrings() {
8282
putTestEntity("BAR", 100);
8383
putTestEntitiesStrings();
8484
putTestEntity("banana", 101);
85-
Query<TestEntity> query = box.query().startsWith(simpleString, "b").build();
85+
Query<TestEntity> query = box.query().startsWith(simpleString, "b", StringOrder.CASE_INSENSITIVE).build();
8686

8787
String[] result = query.property(simpleString).findStrings();
8888
assertEquals(5, result.length);

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

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ public void testBuildTwice() {
7878
queryBuilder.between(TestEntity_.simpleInt, 42, 43);
7979
queryBuilder.in(TestEntity_.simpleInt, new int[]{42});
8080
queryBuilder.notIn(TestEntity_.simpleInt, new int[]{42});
81-
queryBuilder.contains(TestEntity_.simpleString, "42");
82-
queryBuilder.startsWith(TestEntity_.simpleString, "42");
81+
queryBuilder.contains(TestEntity_.simpleString, "42", StringOrder.CASE_INSENSITIVE);
82+
queryBuilder.startsWith(TestEntity_.simpleString, "42", StringOrder.CASE_SENSITIVE);
8383
queryBuilder.order(TestEntity_.simpleInt);
8484
queryBuilder.build().find();
8585
}
@@ -272,11 +272,11 @@ public void testOffsetLimit() {
272272
public void testString() {
273273
List<TestEntity> entities = putTestEntitiesStrings();
274274
int count = entities.size();
275-
assertEquals(1, getUniqueNotNull(box.query().equal(simpleString, "banana").build()).getId());
276-
assertEquals(count - 1, box.query().notEqual(simpleString, "banana").build().count());
277-
assertEquals(4, getUniqueNotNull(box.query().startsWith(simpleString, "ba").endsWith(simpleString, "shake").build())
275+
assertEquals(1, getUniqueNotNull(box.query().equal(simpleString, "banana", StringOrder.CASE_INSENSITIVE).build()).getId());
276+
assertEquals(count - 1, box.query().notEqual(simpleString, "banana", StringOrder.CASE_INSENSITIVE).build().count());
277+
assertEquals(4, getUniqueNotNull(box.query().startsWith(simpleString, "ba", StringOrder.CASE_INSENSITIVE).endsWith(simpleString, "shake", StringOrder.CASE_INSENSITIVE).build())
278278
.getId());
279-
assertEquals(2, box.query().contains(simpleString, "nana").build().count());
279+
assertEquals(2, box.query().contains(simpleString, "nana", StringOrder.CASE_INSENSITIVE).build().count());
280280
}
281281

282282
@Test
@@ -285,12 +285,12 @@ public void testStringArray() {
285285

286286
// Using contains should not work on String array.
287287
Exception exception = assertThrows(UnsupportedOperationException.class,
288-
() -> box.query().contains(simpleStringArray, "banana"));
288+
() -> box.query().contains(simpleStringArray, "banana", StringOrder.CASE_INSENSITIVE));
289289
assertEquals("For String[] only containsElement() is supported at this time.", exception.getMessage());
290290

291291
// containsElement(prop, value) matches if value is equal to one of the array items.
292292
// Verify by not matching entity where 'banana' is only a substring of an array item ('banana milk shake').
293-
List<TestEntity> results = box.query().containsElement(simpleStringArray, "banana").build().find();
293+
List<TestEntity> results = box.query().containsElement(simpleStringArray, "banana", StringOrder.CASE_INSENSITIVE).build().find();
294294
assertEquals(1, results.size());
295295
assertEquals("banana", results.get(0).getSimpleStringArray()[0]);
296296
}
@@ -299,7 +299,7 @@ public void testStringArray() {
299299
public void testStringLess() {
300300
putTestEntitiesStrings();
301301
putTestEntity("BaNaNa Split", 100);
302-
Query<TestEntity> query = box.query().less(simpleString, "banana juice").order(simpleString).build();
302+
Query<TestEntity> query = box.query().less(simpleString, "banana juice", StringOrder.CASE_INSENSITIVE).order(simpleString).build();
303303
List<TestEntity> entities = query.find();
304304
assertEquals(2, entities.size());
305305
assertEquals("apple", entities.get(0).getSimpleString());
@@ -355,7 +355,7 @@ public void string_lessOrEqual_works() {
355355
public void testStringGreater() {
356356
putTestEntitiesStrings();
357357
putTestEntity("FOO", 100);
358-
Query<TestEntity> query = box.query().greater(simpleString, "banana juice").order(simpleString).build();
358+
Query<TestEntity> query = box.query().greater(simpleString, "banana juice", StringOrder.CASE_INSENSITIVE).order(simpleString).build();
359359
List<TestEntity> entities = query.find();
360360
assertEquals(4, entities.size());
361361
assertEquals("banana milk shake", entities.get(0).getSimpleString());
@@ -410,7 +410,7 @@ public void testStringIn() {
410410
putTestEntitiesStrings();
411411
putTestEntity("BAR", 100);
412412
String[] values = {"bar", "foo bar"};
413-
Query<TestEntity> query = box.query().in(simpleString, values).order(simpleString, OrderFlags.CASE_SENSITIVE)
413+
Query<TestEntity> query = box.query().in(simpleString, values, StringOrder.CASE_INSENSITIVE).order(simpleString, OrderFlags.CASE_SENSITIVE)
414414
.build();
415415
List<TestEntity> entities = query.find();
416416
assertEquals(3, entities.size());
@@ -609,15 +609,15 @@ public void testBigResultList() {
609609
}
610610
box.put(entities);
611611
int count = entities.size();
612-
List<TestEntity> entitiesQueried = box.query().equal(simpleString, sameValueForAll).build().find();
612+
List<TestEntity> entitiesQueried = box.query().equal(simpleString, sameValueForAll, StringOrder.CASE_INSENSITIVE).build().find();
613613
assertEquals(count, entitiesQueried.size());
614614
}
615615

616616
@Test
617617
public void testEqualStringOrder() {
618618
putTestEntitiesStrings();
619619
putTestEntity("BAR", 100);
620-
assertEquals(2, box.query().equal(simpleString, "bar").build().count());
620+
assertEquals(2, box.query().equal(simpleString, "bar", StringOrder.CASE_INSENSITIVE).build().count());
621621
assertEquals(1, box.query().equal(simpleString, "bar", StringOrder.CASE_SENSITIVE).build().count());
622622
}
623623

@@ -800,7 +800,7 @@ public void testSetParameter2Floats() {
800800
@Test
801801
public void testSetParameterString() {
802802
putTestEntitiesStrings();
803-
Query<TestEntity> query = box.query().equal(simpleString, "banana").parameterAlias("foo").build();
803+
Query<TestEntity> query = box.query().equal(simpleString, "banana", StringOrder.CASE_INSENSITIVE).parameterAlias("foo").build();
804804
assertEquals(1, getUniqueNotNull(query).getId());
805805
query.setParameter(simpleString, "bar");
806806
assertEquals(3, getUniqueNotNull(query).getId());
@@ -836,7 +836,7 @@ public void parameterAlias_combinedConditions() {
836836
public void testForEach() {
837837
List<TestEntity> testEntities = putTestEntitiesStrings();
838838
final StringBuilder stringBuilder = new StringBuilder();
839-
box.query().startsWith(simpleString, "banana").build()
839+
box.query().startsWith(simpleString, "banana", StringOrder.CASE_INSENSITIVE).build()
840840
.forEach(data -> stringBuilder.append(data.getSimpleString()).append('#'));
841841
assertEquals("banana#banana milk shake#", stringBuilder.toString());
842842

@@ -849,7 +849,7 @@ public void testForEach() {
849849
public void testForEachBreak() {
850850
putTestEntitiesStrings();
851851
final StringBuilder stringBuilder = new StringBuilder();
852-
box.query().startsWith(simpleString, "banana").build()
852+
box.query().startsWith(simpleString, "banana", StringOrder.CASE_INSENSITIVE).build()
853853
.forEach(data -> {
854854
stringBuilder.append(data.getSimpleString());
855855
throw new BreakForEach();
@@ -947,7 +947,7 @@ public void testDescribe() {
947947

948948
// Some conditions.
949949
Query<TestEntity> query = box.query()
950-
.equal(TestEntity_.simpleString, "Hello")
950+
.equal(TestEntity_.simpleString, "Hello", StringOrder.CASE_INSENSITIVE)
951951
.or().greater(TestEntity_.simpleInt, 42)
952952
.build();
953953
String describeActual = query.describe();

tests/objectbox-java-test/src/test/java/io/objectbox/query/QueryTest2.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.objectbox.query;
1818

19+
import io.objectbox.query.QueryBuilder.StringOrder;
1920
import org.junit.Test;
2021

2122
import java.util.List;
@@ -41,7 +42,7 @@ public void newQueryApi() {
4142

4243
// current query API
4344
Query<TestEntity> query = box.query()
44-
.equal(TestEntity_.simpleString, "Fry")
45+
.equal(TestEntity_.simpleString, "Fry", StringOrder.CASE_INSENSITIVE)
4546
.less(TestEntity_.simpleInt, 12)
4647
.or()
4748
.in(TestEntity_.simpleLong, new long[]{1012})

0 commit comments

Comments
 (0)