Skip to content

Commit 33fe756

Browse files
committed
Merge branch 'main' into teamscale-cleanup
2 parents d43a880 + e1c387d commit 33fe756

File tree

58 files changed

+4586
-363
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+4586
-363
lines changed

.github/workflows/pull_request.yml

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
- name: Run Gradle Test
4747
uses: ./actions/gradle-test
4848
with:
49-
gradle_command: :fdb-record-layer-core:test :fdb-record-layer-core:destructiveTest
49+
gradle_command: :fdb-record-layer-core:jar :fdb-record-layer-core:test :fdb-record-layer-core:destructiveTest
5050
gradle_args: -PreleaseBuild=false -PpublishBuild=false
5151
- name: Publish Test Reports
5252
if: always()
@@ -61,6 +61,7 @@ jobs:
6161
name: core-coverage-data
6262
path: |
6363
**/.out/jacoco/*.exec
64+
**/.out/libs/*.jar
6465
include-hidden-files: true
6566
retention-days: 1
6667

@@ -80,7 +81,7 @@ jobs:
8081
- name: Run Gradle Test
8182
uses: ./actions/gradle-test
8283
with:
83-
gradle_command: :fdb-record-layer-lucene:test :fdb-record-layer-lucene:destructiveTest
84+
gradle_command: :fdb-record-layer-lucene:jar :fdb-record-layer-lucene:test :fdb-record-layer-lucene:destructiveTest
8485
gradle_args: -PreleaseBuild=false -PpublishBuild=false
8586
- name: Publish Test Reports
8687
if: always()
@@ -95,6 +96,7 @@ jobs:
9596
name: lucene-coverage-data
9697
path: |
9798
**/.out/jacoco/*.exec
99+
**/.out/libs/*.jar
98100
include-hidden-files: true
99101
retention-days: 1
100102

@@ -114,7 +116,13 @@ jobs:
114116
- name: Run Gradle Test
115117
uses: ./actions/gradle-test
116118
with:
117-
gradle_command: test -x :fdb-record-layer-core:test -x :fdb-record-layer-lucene:test destructiveTest -x :fdb-record-layer-core:destructiveTest -x :fdb-record-layer-lucene:destructiveTest
119+
gradle_command: >-
120+
test
121+
-x :fdb-record-layer-core:test
122+
-x :fdb-record-layer-lucene:test
123+
destructiveTest
124+
-x :fdb-record-layer-core:destructiveTest
125+
-x :fdb-record-layer-lucene:destructiveTest
118126
gradle_args: -PreleaseBuild=false -PpublishBuild=false
119127
- name: Publish Test Reports
120128
if: always()
@@ -156,12 +164,20 @@ jobs:
156164
uses: actions/[email protected]
157165
- name: Setup Base Environment
158166
uses: ./actions/setup-base-env
159-
- name: 'Download artifacts'
167+
# It looks like, if you try to download them all as a pattern, the nested directories get stripped
168+
# so the coverage data (for e.g. lucene) does not end up in the appropirate subproject directory
169+
- name: 'Download lucene'
170+
uses: actions/download-artifact@v4
171+
with:
172+
name: lucene-coverage-data
173+
- name: 'Download core'
160174
uses: actions/download-artifact@v4
161175
with:
162-
pattern: |
163-
*-coverage-data
164-
merge-multiple: true
176+
name: core-coverage-data
177+
- name: 'Download other'
178+
uses: actions/download-artifact@v4
179+
with:
180+
name: other-coverage-data
165181
- name: Run JaCoCo Report
166182
uses: ./actions/run-gradle
167183
with:

.github/workflows/teamscale_upload.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
- name: 'Unzip artifact'
4444
run: unzip "${{ runner.temp }}/artifacts/coverage-report.zip" -d "${{ runner.temp }}/artifacts"
4545
- name: 'Upload coverage'
46-
uses: 'cqse/teamscale-upload-action@v2.9.6'
46+
uses: 'cqse/teamscale-upload-action@8d10b6693b9242420ef2062dbefc36af6e88d587'
4747
with:
4848
server: 'https://fdb.teamscale.io'
4949
project: 'foundationdb-fdb-record-layer'

docs/sphinx/source/ReleaseNotes.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,41 @@ As the [versioning guide](Versioning.md) details, it cannot always be determined
77

88
## 4.5
99

10+
### 4.5.5.0
11+
12+
<h4> New Features </h4>
13+
14+
* Bring back full support for UUID - [PR #3510](https://github.com/FoundationDB/fdb-record-layer/pull/3510)
15+
<h4> Bug Fixes </h4>
16+
17+
* Unpivoting repeated fields with SQL functions - [PR #3537](https://github.com/FoundationDB/fdb-record-layer/pull/3537)
18+
19+
<details>
20+
<summary>
21+
22+
<h4> Build/Test/Documentation/Style Improvements (click to expand) </h4>
23+
24+
</summary>
25+
26+
* Add more prefix-based tests to like.yamsql - [PR #3536](https://github.com/FoundationDB/fdb-record-layer/pull/3536)
27+
* Fully qualify teamscale action - [PR #3534](https://github.com/FoundationDB/fdb-record-layer/pull/3534)
28+
* Upload coverage data to teamscale - [PR #3519](https://github.com/FoundationDB/fdb-record-layer/pull/3519)
29+
30+
</details>
31+
32+
33+
**[Full Changelog (4.5.4.0...4.5.5.0)](https://github.com/FoundationDB/fdb-record-layer/compare/4.5.4.0...4.5.5.0)**
34+
35+
#### Mixed Mode Test Results
36+
37+
Mixed mode testing run against the following previous versions:
38+
39+
`4.4.9.0`, ❌`4.4.10.0`, ❌`4.4.11.0`, ✅`4.4.12.0`, ✅`4.4.14.0`, ✅`4.4.15.0`, ✅`4.5.1.0`, ✅`4.5.2.0`, ✅`4.5.3.0`, ✅`4.5.4.0`
40+
41+
[See full test run](https://github.com/FoundationDB/fdb-record-layer/actions/runs/16915773485)
42+
43+
44+
1045
### 4.5.4.0
1146

1247
<h4> New Features </h4>

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/expressions/Comparisons.java

Lines changed: 63 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import com.apple.foundationdb.record.util.ProtoUtils;
7474
import com.apple.foundationdb.tuple.ByteArrayUtil;
7575
import com.apple.foundationdb.tuple.ByteArrayUtil2;
76+
import com.apple.foundationdb.tuple.Tuple;
7677
import com.google.auto.service.AutoService;
7778
import com.google.common.base.Suppliers;
7879
import com.google.common.base.Verify;
@@ -211,11 +212,9 @@ private static Comparable toComparable(@Nullable Object obj) {
211212
}
212213
}
213214

214-
@Nullable
215-
public static Object toClassWithRealEquals(@Nullable Object obj) {
216-
if (obj == null) {
217-
return null;
218-
} else if (obj instanceof ByteString) {
215+
@Nonnull
216+
public static Object toClassWithRealEquals(@Nonnull Object obj) {
217+
if (obj instanceof ByteString) {
219218
return obj;
220219
} else if (obj instanceof byte[]) {
221220
return ByteString.copyFrom((byte[])obj);
@@ -231,30 +230,30 @@ public static Object toClassWithRealEquals(@Nullable Object obj) {
231230
}
232231

233232
@SuppressWarnings("unchecked")
234-
public static int compare(@Nullable Object fieldValue, @Nullable Object comparand) {
235-
if (fieldValue == null) {
236-
if (comparand == null) {
237-
return 0;
238-
} else {
239-
return -1;
240-
}
241-
} else if (comparand == null) {
242-
return 1;
233+
public static int compare(@Nonnull Object fieldValue, @Nonnull Object comparand) {
234+
return toComparable(fieldValue).compareTo(toComparable(comparand));
235+
}
236+
237+
@SpotBugsSuppressWarnings("NP_BOOLEAN_RETURN_NULL")
238+
private static boolean compareEquals(@Nonnull Object value, @Nonnull Object comparand) {
239+
if (value instanceof Message) {
240+
return MessageHelpers.compareMessageEquals(value, comparand);
243241
} else {
244-
return toComparable(fieldValue).compareTo(toComparable(comparand));
242+
return toClassWithRealEquals(value).equals(toClassWithRealEquals(comparand));
245243
}
246244
}
247245

248-
@Nullable
249246
@SpotBugsSuppressWarnings("NP_BOOLEAN_RETURN_NULL")
250-
private static Boolean compareEquals(Object value, Object comparand) {
251-
if (value == null || comparand == null) {
252-
return null;
247+
private static boolean compareNotDistinctFrom(@Nullable Object value, @Nullable Object comparand) {
248+
if (value == null && comparand == null) {
249+
return true;
250+
} else if (value == null || comparand == null) {
251+
return false;
253252
} else {
254253
if (value instanceof Message) {
255254
return MessageHelpers.compareMessageEquals(value, comparand);
256255
} else {
257-
return toClassWithRealEquals(value).equals(toClassWithRealEquals(comparand));
256+
return toClassWithRealEquals(Objects.requireNonNull(value)).equals(toClassWithRealEquals(Objects.requireNonNull(comparand)));
258257
}
259258
}
260259
}
@@ -283,6 +282,9 @@ private static Boolean compareStartsWith(@Nullable Object value, @Nullable Objec
283282
@Nullable
284283
@SpotBugsSuppressWarnings("NP_BOOLEAN_RETURN_NULL")
285284
private static Boolean compareLike(@Nullable Object value, @Nullable Object pattern) {
285+
if (value == null) {
286+
return null;
287+
}
286288
if (!(value instanceof String)) {
287289
throw new RecordCoreException("Illegal comparand value type: " + value);
288290
}
@@ -311,7 +313,12 @@ private static Boolean compareListStartsWith(@Nullable Object value, @Nonnull Li
311313
if (i > list.size()) {
312314
return false;
313315
}
314-
if (!toClassWithRealEquals(comparand.get(i)).equals(toClassWithRealEquals(list.get(i)))) {
316+
if (comparand.get(i) == null && list.get(i) == null) {
317+
continue;
318+
}
319+
if (comparand.get(i) == null || list.get(i) == null) {
320+
return false;
321+
} else if (!toClassWithRealEquals(comparand.get(i)).equals(toClassWithRealEquals(list.get(i)))) {
315322
return false;
316323
}
317324
}
@@ -336,11 +343,12 @@ private static Boolean compareIn(@Nullable Object value, @Nullable Object compar
336343
return true;
337344
}
338345
} else {
339-
if (toClassWithRealEquals(value).equals(toClassWithRealEquals(comparandItem))) {
346+
if (comparandItem == null) {
347+
hasNull = true;
348+
} else if (toClassWithRealEquals(value).equals(toClassWithRealEquals(comparandItem))) {
340349
return true;
341350
}
342351
}
343-
hasNull |= comparandItem == null;
344352
}
345353
return hasNull ? null : false;
346354
} else {
@@ -632,7 +640,9 @@ public enum Type {
632640
@API(API.Status.EXPERIMENTAL)
633641
SORT(false),
634642
@API(API.Status.EXPERIMENTAL)
635-
LIKE;
643+
LIKE,
644+
IS_DISTINCT_FROM(false),
645+
NOT_DISTINCT_FROM(true);
636646

637647
@Nonnull
638648
private static final Supplier<BiMap<Type, PComparisonType>> protoEnumBiMapSupplier =
@@ -682,7 +692,7 @@ private static BiMap<Type, PComparisonType> getProtoEnumBiMap() {
682692
}
683693

684694
@Nullable
685-
public static Type invertComparisonType(@Nonnull final Comparisons.Type type) {
695+
public static Type invertComparisonType(@Nonnull final Type type) {
686696
if (type.isUnary()) {
687697
return null;
688698
}
@@ -705,28 +715,44 @@ public static Type invertComparisonType(@Nonnull final Comparisons.Type type) {
705715
@Nullable
706716
@SpotBugsSuppressWarnings("NP_BOOLEAN_RETURN_NULL")
707717
public static Boolean evalComparison(@Nonnull Type type, @Nullable Object value, @Nullable Object comparand) {
708-
if (value == null) {
709-
return null;
710-
}
711718
switch (type) {
712719
case STARTS_WITH:
713720
return compareStartsWith(value, comparand);
714721
case IN:
715722
return compareIn(value, comparand);
716723
case EQUALS:
724+
if (value == null || comparand == null) {
725+
return null;
726+
}
717727
return compareEquals(value, comparand);
718728
case NOT_EQUALS:
719-
if (comparand == null) {
729+
if (value == null || comparand == null) {
720730
return null;
721731
}
722732
return !compareEquals(value, comparand);
733+
case IS_DISTINCT_FROM:
734+
return !compareNotDistinctFrom(value, comparand);
735+
case NOT_DISTINCT_FROM:
736+
return compareNotDistinctFrom(value, comparand);
723737
case LESS_THAN:
738+
if (value == null || comparand == null) {
739+
return null;
740+
}
724741
return compare(value, comparand) < 0;
725742
case LESS_THAN_OR_EQUALS:
743+
if (value == null || comparand == null) {
744+
return null;
745+
}
726746
return compare(value, comparand) <= 0;
727747
case GREATER_THAN:
748+
if (value == null || comparand == null) {
749+
return null;
750+
}
728751
return compare(value, comparand) > 0;
729752
case GREATER_THAN_OR_EQUALS:
753+
if (value == null || comparand == null) {
754+
return null;
755+
}
730756
return compare(value, comparand) >= 0;
731757
case LIKE:
732758
return compareLike(value, comparand);
@@ -823,7 +849,7 @@ default Object getComparand() {
823849

824850
/**
825851
* Get whether the comparison is with the result of a multi-column key.
826-
* If so, {@link #getComparand} will return a {@link com.apple.foundationdb.tuple.Tuple}.
852+
* If so, {@link #getComparand} will return a {@link Tuple}.
827853
* @return {@code true} if the comparand is for multiple key columns
828854
*/
829855
default boolean hasMultiColumnComparand() {
@@ -1302,9 +1328,7 @@ public ConstrainedBoolean semanticEqualsTyped(@Nonnull final Comparison other, @
13021328
public Boolean eval(@Nullable FDBRecordStoreBase<?> store, @Nonnull EvaluationContext context, @Nullable Object value) {
13031329
// this is at evaluation time --> always use the context binding
13041330
final Object comparand = getComparand(store, context);
1305-
if (comparand == null) {
1306-
return null;
1307-
} else if (comparand == COMPARISON_SKIPPED_BINDING) {
1331+
if (comparand == COMPARISON_SKIPPED_BINDING) {
13081332
return Boolean.TRUE;
13091333
} else {
13101334
return evalComparison(type, value, comparand);
@@ -1620,9 +1644,7 @@ public ConstrainedBoolean semanticEqualsTyped(@Nonnull final Comparison other, @
16201644
public Boolean eval(@Nullable FDBRecordStoreBase<?> store, @Nonnull EvaluationContext context, @Nullable Object v) {
16211645
// this is at evaluation time --> always use the context binding
16221646
final Object comparand = getComparand(store, context);
1623-
if (comparand == null) {
1624-
return null;
1625-
} else if (comparand == COMPARISON_SKIPPED_BINDING) {
1647+
if (comparand == COMPARISON_SKIPPED_BINDING) {
16261648
return Boolean.TRUE;
16271649
} else {
16281650
return evalComparison(type, v, comparand);
@@ -1739,7 +1761,7 @@ public static class ListComparison implements Comparison {
17391761
@SuppressWarnings("rawtypes")
17401762
private final List comparand;
17411763
@Nullable
1742-
private final Descriptors.FieldDescriptor.JavaType javaType;
1764+
private final JavaType javaType;
17431765

17441766
@Nonnull
17451767
@SuppressWarnings("rawtypes")
@@ -1757,8 +1779,8 @@ public ListComparison(@Nonnull Type type, @Nonnull List comparand) {
17571779
default:
17581780
throw new RecordCoreException("ListComparison only supports EQUALS, NOT_EQUALS, STARTS_WITH and IN");
17591781
}
1760-
if (comparand == null || (this.type == Type.IN && comparand.stream().anyMatch(o -> o == null))) {
1761-
throw new NullPointerException("List comparand is null, or contains null");
1782+
if (this.type == Type.IN && comparand.stream().anyMatch(o -> o == null)) {
1783+
throw new NullPointerException("List comparand contains null");
17621784
}
17631785
if (comparand.isEmpty()) {
17641786
javaType = null;
@@ -1772,10 +1794,10 @@ public ListComparison(@Nonnull Type type, @Nonnull List comparand) {
17721794
}
17731795
}
17741796
this.comparand = comparand;
1775-
this.comparandListWithEqualsSupplier = Suppliers.memoize(() -> Lists.transform(comparand, Comparisons::toClassWithRealEquals));
1797+
this.comparandListWithEqualsSupplier = Suppliers.memoize(() -> Lists.transform(comparand, obj -> obj != null ? toClassWithRealEquals(obj) : null));
17761798
}
17771799

1778-
private static Descriptors.FieldDescriptor.JavaType getJavaType(@Nonnull Object o) {
1800+
private static JavaType getJavaType(@Nonnull Object o) {
17791801
if (o instanceof Boolean) {
17801802
return JavaType.BOOLEAN;
17811803
} else if (o instanceof ByteString || o instanceof byte[]) {

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/RangeConstraints.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,8 @@ private boolean canBeUsedInScanPrefix(@Nonnull final Comparisons.Comparison comp
763763
case STARTS_WITH:
764764
case NOT_NULL:
765765
case IS_NULL:
766+
case NOT_DISTINCT_FROM:
767+
case IS_DISTINCT_FROM:
766768
return true;
767769
case TEXT_CONTAINS_ALL:
768770
case TEXT_CONTAINS_ALL_WITHIN:

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/typing/Type.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ private static Type fromProtoType(@Nullable Descriptors.GenericDescriptor descri
434434
final var elementField = messageDescriptor.findFieldByName(NullableArrayTypeUtils.getRepeatedFieldName());
435435
final var elementTypeCode = TypeCode.fromProtobufType(elementField.getType());
436436
return fromProtoTypeToArray(descriptor, protoType, elementTypeCode, true);
437+
} else if (TupleFieldsProto.UUID.getDescriptor().equals(messageDescriptor)) {
438+
return Type.uuidType(isNullable);
437439
} else {
438440
return Record.fromFieldDescriptorsMap(isNullable, Record.toFieldDescriptorMap(messageDescriptor.getFields()));
439441
}
@@ -2475,7 +2477,8 @@ public boolean equals(final Object o) {
24752477
}
24762478
final var field = (Field)o;
24772479
return getFieldType().equals(field.getFieldType()) &&
2478-
getFieldNameOptional().equals(field.getFieldNameOptional());
2480+
getFieldNameOptional().equals(field.getFieldNameOptional()) &&
2481+
getFieldIndexOptional().equals(field.getFieldIndexOptional());
24792482
}
24802483

24812484
@Override

0 commit comments

Comments
 (0)