Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit 81e6857

Browse files
committed
feat: DML prototype
1 parent 2f37c41 commit 81e6857

13 files changed

Lines changed: 710 additions & 0 deletions

File tree

google-cloud-firestore/src/main/java/com/google/cloud/firestore/Pipeline.java

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@
4141
import com.google.cloud.firestore.pipeline.stages.AddFields;
4242
import com.google.cloud.firestore.pipeline.stages.Aggregate;
4343
import com.google.cloud.firestore.pipeline.stages.AggregateOptions;
44+
import com.google.cloud.firestore.pipeline.stages.Delete;
45+
import com.google.cloud.firestore.pipeline.stages.DeleteOptions;
4446
import com.google.cloud.firestore.pipeline.stages.Distinct;
4547
import com.google.cloud.firestore.pipeline.stages.FindNearest;
4648
import com.google.cloud.firestore.pipeline.stages.FindNearestOptions;
49+
import com.google.cloud.firestore.pipeline.stages.Insert;
50+
import com.google.cloud.firestore.pipeline.stages.InsertOptions;
4751
import com.google.cloud.firestore.pipeline.stages.Limit;
4852
import com.google.cloud.firestore.pipeline.stages.Offset;
4953
import com.google.cloud.firestore.pipeline.stages.PipelineExecuteOptions;
@@ -58,6 +62,8 @@
5862
import com.google.cloud.firestore.pipeline.stages.Union;
5963
import com.google.cloud.firestore.pipeline.stages.Unnest;
6064
import com.google.cloud.firestore.pipeline.stages.UnnestOptions;
65+
import com.google.cloud.firestore.pipeline.stages.Upsert;
66+
import com.google.cloud.firestore.pipeline.stages.UpsertOptions;
6167
import com.google.cloud.firestore.pipeline.stages.Where;
6268
import com.google.cloud.firestore.telemetry.MetricsUtil.MetricsContext;
6369
import com.google.cloud.firestore.telemetry.TelemetryConstants;
@@ -995,6 +1001,105 @@ public Pipeline unnest(Selectable field, UnnestOptions options) {
9951001
return append(new Unnest(field, options));
9961002
}
9971003

1004+
/**
1005+
* Performs a delete operation on documents from previous stages.
1006+
*
1007+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1008+
*/
1009+
@BetaApi
1010+
public Pipeline delete() {
1011+
return append(new Delete());
1012+
}
1013+
1014+
/**
1015+
* Performs a delete operation on documents from previous stages.
1016+
*
1017+
* @param target The collection to delete from.
1018+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1019+
*/
1020+
@BetaApi
1021+
public Pipeline delete(CollectionReference target) {
1022+
return append(Delete.withCollection(target));
1023+
}
1024+
1025+
/**
1026+
* Performs a delete operation on documents from previous stages.
1027+
*
1028+
* @param deleteStage The {@code Delete} stage to append.
1029+
* @param options The {@code DeleteOptions} to apply to the stage.
1030+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1031+
*/
1032+
@BetaApi
1033+
public Pipeline delete(Delete deleteStage, DeleteOptions options) {
1034+
return append(deleteStage.withOptions(options));
1035+
}
1036+
1037+
/**
1038+
* Performs an upsert operation using documents from previous stages.
1039+
*
1040+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1041+
*/
1042+
@BetaApi
1043+
public Pipeline upsert() {
1044+
return append(new Upsert());
1045+
}
1046+
1047+
/**
1048+
* Performs an upsert operation using documents from previous stages.
1049+
*
1050+
* @param target The collection to upsert to.
1051+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1052+
*/
1053+
@BetaApi
1054+
public Pipeline upsert(CollectionReference target) {
1055+
return append(Upsert.withCollection(target));
1056+
}
1057+
1058+
/**
1059+
* Performs an upsert operation using documents from previous stages.
1060+
*
1061+
* @param upsertStage The {@code Upsert} stage to append.
1062+
* @param options The {@code UpsertOptions} to apply to the stage.
1063+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1064+
*/
1065+
@BetaApi
1066+
public Pipeline upsert(Upsert upsertStage, UpsertOptions options) {
1067+
return append(upsertStage.withOptions(options));
1068+
}
1069+
1070+
/**
1071+
* Performs an insert operation using documents from previous stages.
1072+
*
1073+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1074+
*/
1075+
@BetaApi
1076+
public Pipeline insert() {
1077+
return append(new Insert());
1078+
}
1079+
1080+
/**
1081+
* Performs an insert operation using documents from previous stages.
1082+
*
1083+
* @param target The collection to insert to.
1084+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1085+
*/
1086+
@BetaApi
1087+
public Pipeline insert(CollectionReference target) {
1088+
return append(Insert.withCollection(target));
1089+
}
1090+
1091+
/**
1092+
* Performs an insert operation using documents from previous stages.
1093+
*
1094+
* @param insertStage The {@code Insert} stage to append.
1095+
* @param options The {@code InsertOptions} to apply to the stage.
1096+
* @return A new {@code Pipeline} object with this stage appended to the stage list.
1097+
*/
1098+
@BetaApi
1099+
public Pipeline insert(Insert insertStage, InsertOptions options) {
1100+
return append(insertStage.withOptions(options));
1101+
}
1102+
9981103
/**
9991104
* Adds a generic stage to the pipeline.
10001105
*
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore.pipeline.stages;
18+
19+
/** Defines the conflict resolution options for an Upsert pipeline stage. */
20+
public enum ConflictResolution {
21+
OVERWRITE("OVERWRITE"),
22+
MERGE("MERGE"),
23+
FAIL("FAIL"),
24+
KEEP("KEEP");
25+
26+
private final String value;
27+
28+
ConflictResolution(String value) {
29+
this.value = value;
30+
}
31+
32+
public String getValue() {
33+
return value;
34+
}
35+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore.pipeline.stages;
18+
19+
import com.google.api.core.BetaApi;
20+
import com.google.api.core.InternalApi;
21+
import com.google.cloud.firestore.CollectionReference;
22+
import com.google.cloud.firestore.PipelineUtils;
23+
import com.google.firestore.v1.Value;
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
import javax.annotation.Nullable;
27+
28+
@InternalApi
29+
public final class Delete extends Stage {
30+
31+
@Nullable private final String path;
32+
33+
private Delete(@Nullable String path, InternalOptions options) {
34+
super("delete", options);
35+
this.path = path;
36+
}
37+
38+
@BetaApi
39+
public Delete() {
40+
this(null, InternalOptions.EMPTY);
41+
}
42+
43+
@BetaApi
44+
public static Delete withCollection(CollectionReference target) {
45+
String path = target.getPath();
46+
return new Delete(path.startsWith("/") ? path : "/" + path, InternalOptions.EMPTY);
47+
}
48+
49+
@BetaApi
50+
public Delete withOptions(DeleteOptions options) {
51+
return new Delete(path, this.options.adding(options));
52+
}
53+
54+
@BetaApi
55+
public Delete withReturns(DeleteReturn returns) {
56+
return new Delete(
57+
path, this.options.with("returns", PipelineUtils.encodeValue(returns.getValue())));
58+
}
59+
60+
@Override
61+
Iterable<Value> toStageArgs() {
62+
List<Value> args = new ArrayList<>();
63+
if (path != null) {
64+
args.add(Value.newBuilder().setReferenceValue(path).build());
65+
}
66+
return args;
67+
}
68+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore.pipeline.stages;
18+
19+
import com.google.api.core.BetaApi;
20+
21+
/** Options for a Delete pipeline stage. */
22+
@BetaApi
23+
public class DeleteOptions extends WriteOptions<DeleteOptions> {
24+
25+
/** Creates a new, empty `DeleteOptions` object. */
26+
public DeleteOptions() {
27+
super(InternalOptions.EMPTY);
28+
}
29+
30+
DeleteOptions(InternalOptions options) {
31+
super(options);
32+
}
33+
34+
@Override
35+
DeleteOptions self(InternalOptions options) {
36+
return new DeleteOptions(options);
37+
}
38+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore.pipeline.stages;
18+
19+
/** Defines the return value options for a Delete pipeline stage. */
20+
public enum DeleteReturn {
21+
EMPTY("EMPTY"),
22+
DOCUMENT_ID("DOCUMENT_ID");
23+
24+
private final String value;
25+
26+
DeleteReturn(String value) {
27+
this.value = value;
28+
}
29+
30+
public String getValue() {
31+
return value;
32+
}
33+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore.pipeline.stages;
18+
19+
import com.google.api.core.BetaApi;
20+
import com.google.api.core.InternalApi;
21+
import com.google.cloud.firestore.CollectionReference;
22+
import com.google.cloud.firestore.PipelineUtils;
23+
import com.google.cloud.firestore.pipeline.expressions.Selectable;
24+
import com.google.firestore.v1.Value;
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
import javax.annotation.Nullable;
28+
29+
@InternalApi
30+
public final class Insert extends Stage {
31+
32+
@Nullable private final String path;
33+
34+
private Insert(@Nullable String path, InternalOptions options) {
35+
super("insert", options);
36+
this.path = path;
37+
}
38+
39+
@BetaApi
40+
public Insert() {
41+
this(null, InternalOptions.EMPTY);
42+
}
43+
44+
@BetaApi
45+
public static Insert withCollection(CollectionReference target) {
46+
String path = target.getPath();
47+
return new Insert(path.startsWith("/") ? path : "/" + path, InternalOptions.EMPTY);
48+
}
49+
50+
@BetaApi
51+
public Insert withOptions(InsertOptions options) {
52+
return new Insert(path, this.options.adding(options));
53+
}
54+
55+
@BetaApi
56+
public Insert withReturns(InsertReturn returns) {
57+
return new Insert(
58+
path, this.options.with("returns", PipelineUtils.encodeValue(returns.getValue())));
59+
}
60+
61+
@BetaApi
62+
public Insert withTransformations(Selectable... transformations) {
63+
return new Insert(
64+
path,
65+
this.options.with(
66+
"transformations",
67+
PipelineUtils.encodeValue(PipelineUtils.selectablesToMap(transformations))));
68+
}
69+
70+
@Override
71+
Iterable<Value> toStageArgs() {
72+
List<Value> args = new ArrayList<>();
73+
if (path != null) {
74+
args.add(Value.newBuilder().setReferenceValue(path).build());
75+
}
76+
return args;
77+
}
78+
}

0 commit comments

Comments
 (0)