From 48b9614340953609cdc82231524b446fa6f49f4e Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 23 Jul 2024 12:26:31 -0600 Subject: [PATCH 01/59] Create and document Java sync improved bulk write API JAVA-5527 --- .../com/mongodb/ClientBulkWriteException.java | 143 +++++++ .../model/bulk/ClientBulkWriteOptions.java | 91 +++++ .../model/bulk/ClientDeleteOptions.java | 65 +++ .../model/bulk/ClientReplaceOptions.java | 73 ++++ .../model/bulk/ClientUpdateOptions.java | 83 ++++ .../client/model/bulk/ClientWriteModel.java | 369 ++++++++++++++++++ .../client/model/bulk/package-info.java | 23 ++ .../result/bulk/ClientBulkWriteResult.java | 141 +++++++ .../result/bulk/ClientDeleteResult.java | 36 ++ .../result/bulk/ClientInsertOneResult.java | 37 ++ .../result/bulk/ClientUpdateResult.java | 54 +++ .../client/result/bulk/package-info.java | 23 ++ .../model/bulk/ClientDeleteManyModel.java | 49 +++ .../model/bulk/ClientDeleteOneModel.java | 49 +++ .../model/bulk/ClientInsertOneModel.java | 42 ++ .../model/bulk/ClientReplaceOneModel.java | 53 +++ .../model/bulk/ClientUpdateManyModel.java | 63 +++ .../model/bulk/ClientUpdateOneModel.java | 63 +++ .../bulk/ConcreteClientBulkWriteOptions.java | 85 ++++ .../bulk/ConcreteClientDeleteOptions.java | 67 ++++ .../bulk/ConcreteClientReplaceOptions.java | 76 ++++ .../bulk/ConcreteClientUpdateOptions.java | 85 ++++ .../client/model/bulk/package-info.java | 23 ++ ...nowledgedSummaryClientBulkWriteResult.java | 134 +++++++ ...nowledgedVerboseClientBulkWriteResult.java | 133 +++++++ .../bulk/ConcreteClientDeleteResult.java | 58 +++ .../bulk/ConcreteClientInsertOneResult.java | 61 +++ .../bulk/ConcreteClientUpdateResult.java | 87 +++++ .../UnacknowledgedClientBulkWriteResult.java | 92 +++++ .../client/result/bulk/package-info.java | 23 ++ .../coroutine/syncadapter/SyncMongoCluster.kt | 35 ++ .../client/syncadapter/SyncMongoCluster.kt | 35 ++ .../client/syncadapter/SyncMongoClient.java | 36 ++ .../client/syncadapter/SyncMongoCluster.java | 37 ++ .../scala/syncadapter/SyncMongoCluster.scala | 32 ++ .../main/com/mongodb/client/MongoCluster.java | 97 +++++ .../client/internal/MongoClientImpl.java | 36 ++ .../client/internal/MongoClusterImpl.java | 49 +++ 38 files changed, 2738 insertions(+) create mode 100644 driver-core/src/main/com/mongodb/ClientBulkWriteException.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOptions.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOptions.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOptions.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/package-info.java create mode 100644 driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java create mode 100644 driver-core/src/main/com/mongodb/client/result/bulk/ClientDeleteResult.java create mode 100644 driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java create mode 100644 driver-core/src/main/com/mongodb/client/result/bulk/ClientUpdateResult.java create mode 100644 driver-core/src/main/com/mongodb/client/result/bulk/package-info.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/package-info.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java new file mode 100644 index 00000000000..66c428a4222 --- /dev/null +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -0,0 +1,143 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb; + +import com.mongodb.bulk.WriteConcernError; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.lang.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static com.mongodb.assertions.Assertions.isTrueArgument; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableMap; +import static java.util.Optional.ofNullable; + +/** + * The result of an unsuccessful or partially unsuccessful client-level bulk write operation. + * + * @see ClientBulkWriteResult + * @since 5.3 + * @serial exclude + */ +public final class ClientBulkWriteException extends MongoServerException { + private static final long serialVersionUID = 1; + + @Nullable + private final MongoException error; + private final List writeConcernErrors; + private final Map writeErrors; + @Nullable + private final ClientBulkWriteResult partialResult; + + private ClientBulkWriteException( + final String message, + @Nullable final MongoException error, + @Nullable final List writeConcernErrors, + @Nullable final Map writeErrors, + @Nullable final ClientBulkWriteResult partialResult, + final ServerAddress serverAddress) { + super(message, serverAddress); + // BULK-TODO Should ClientBulkWriteException.getCode be the same as error.getCode, + // and getErrorLabels/hasErrorLabel contain the same labels as error.getErrorLabels? + this.error = error; + this.writeConcernErrors = writeConcernErrors == null ? emptyList() : unmodifiableList(writeConcernErrors); + this.writeErrors = writeErrors == null ? emptyMap() : unmodifiableMap(writeErrors); + this.partialResult = partialResult; + } + + /** + * Creates a {@link ClientBulkWriteException}. + * At least one of {@code error}, {@code writeConcernErrors}, {@code writeErrors}, {@code partialResult} + * must be non-{@code null} or non-empty. + * + * @param error The {@linkplain #getError() top-level error}. + * @param writeConcernErrors The {@linkplain #getWriteConcernErrors() write concern errors}. + * @param writeErrors The {@linkplain #getWriteErrors() write errors}. + * @param partialResult The {@linkplain #getPartialResult() partial result}. + * @param serverAddress The {@linkplain MongoServerException#getServerAddress() server address}. + * @return The requested {@link ClientBulkWriteException}. + */ + public static ClientBulkWriteException create( + @Nullable final MongoException error, + @Nullable final List writeConcernErrors, + @Nullable final Map writeErrors, + @Nullable final ClientBulkWriteResult partialResult, + final ServerAddress serverAddress) { + isTrueArgument("At least one of `writeConcernErrors`, `writeErrors`, `partialResult` must be non-null or non-empty", + !(writeConcernErrors == null || writeConcernErrors.isEmpty()) + || !(writeErrors == null || writeErrors.isEmpty()) + || partialResult != null); + String message = "Client-level bulk write operation error on server " + serverAddress + "." + + (error == null ? "" : " Top-level error: " + error + ".") + + (writeErrors == null || writeErrors.isEmpty() ? "" : " Write errors: " + writeErrors + ".") + + (writeConcernErrors == null || writeConcernErrors.isEmpty() ? "" : " Write concern errors: " + writeConcernErrors + ".") + + (partialResult == null ? "" : " Partial result: " + partialResult + "."); + return new ClientBulkWriteException(message, error, writeConcernErrors, writeErrors, partialResult, serverAddress); + } + + /** + * The top-level error. That is an error that is neither a {@linkplain #getWriteConcernErrors() write concern error}, + * nor is an {@linkplain #getWriteErrors() error of an individual write operation}. + * + * @return The top-level error. {@linkplain Optional#isPresent() Present} only if a top-level error occurred. + */ + public Optional getError() { + return ofNullable(error); + } + + /** + * The {@link WriteConcernError}s that occurred while executing the client-level bulk write operation. + *

+ * There are no guarantees on mutability of the {@link List} returned.

+ * + * @return The {@link WriteConcernError}s. + */ + public List getWriteConcernErrors() { + return writeConcernErrors; + } + + /** + * The indexed {@link WriteError}s. + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * in the corresponding client-level bulk write operation. + *

+ * There are no guarantees on mutability or iteration order of the {@link Map} returned.

+ * + * @return The indexed {@link WriteError}s. + * @see ClientBulkWriteResult#getInsertResults() + * @see ClientBulkWriteResult#getUpdateResults() + * @see ClientBulkWriteResult#getDeleteResults() + */ + public Map getWriteErrors() { + return writeErrors; + } + + /** + * The result of the successful part of a client-level bulk write operation. + * + * @return The successful partial result. {@linkplain Optional#isPresent() Present} only if at least one + * {@linkplain ClientWriteModel individual write operation} succeed. + */ + public Optional getPartialResult() { + return ofNullable(partialResult); + } +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java new file mode 100644 index 00000000000..0ffce0c8063 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java @@ -0,0 +1,91 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; +import com.mongodb.client.model.Filters; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.internal.client.model.bulk.ConcreteClientBulkWriteOptions; +import com.mongodb.lang.Nullable; +import org.bson.BsonValue; +import org.bson.conversions.Bson; + +/** + * The options to apply when executing a client-level bulk write operation. + * + * @since 5.3 + */ +@Sealed +public interface ClientBulkWriteOptions { + /** + * Creates the default options. + * + * @return The default options. + */ + static ClientBulkWriteOptions clientBulkWriteOptions() { + return new ConcreteClientBulkWriteOptions(); + } + + /** + * Enables or disables ordered execution of {@linkplain ClientWriteModel individual write operations}. + * In an ordered execution a failure of an individual operation prevents the rest of them + * from being executed. + * In an unordered execution failures of individual operations do not prevent the rest of them + * from being executed. + * + * @param ordered The ordered flag. If {@code null}, the client defaults to {@code true}. + * @return {@code this}. + */ + ClientBulkWriteOptions ordered(@Nullable Boolean ordered); + + /** + * Disables or enables checking against document validation rules, a.k.a., schema validation. + * + * @param bypassDocumentValidation The flag specifying whether to bypass the document validation rules. + * {@code null} represents the server default. + * @return {@code this}. + */ + ClientBulkWriteOptions bypassDocumentValidation(@Nullable Boolean bypassDocumentValidation); + + /** + * Sets variables that can be referenced from {@linkplain ClientWriteModel individual write operations} + * with the {@code "$$"} syntax, which in turn requires using {@link Filters#expr(Object)} when specifying filters. + * Values must be constants or expressions that do not reference fields. + * + * @param let The variables. {@code null} represents the server default. + * @return {@code this}. + * @mongodb.driver.manual reference/aggregation-variables/ Variables in Aggregation Expressions + */ + ClientBulkWriteOptions let(@Nullable Bson let); + + /** + * Sets the comment to attach to the {@code bulkWrite} administration command. + * + * @param comment The comment. {@code null} represents the server default. + * @return {@code this}. + */ + ClientBulkWriteOptions comment(@Nullable BsonValue comment); + + /** + * Enables or disables requesting {@linkplain ClientBulkWriteResult#hasVerboseResults() verbose results}. + * + * @param verboseResults The flag specifying whether to request verbose results. + * If {@code null}, the client defaults to {@code false}. + * This value corresponds inversely to the {@code errorsOnly} field of the {@code bulkWrite} administration command. + * @return {@code this}. + */ + ClientBulkWriteOptions verboseResults(@Nullable Boolean verboseResults); +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOptions.java new file mode 100644 index 00000000000..54b941776e0 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOptions.java @@ -0,0 +1,65 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; +import com.mongodb.client.model.Collation; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * The options to apply when deleting documents. + * + * @since 5.3 + */ +@Sealed +public interface ClientDeleteOptions { + /** + * Creates the default options. + * + * @return The default options. + */ + static ClientDeleteOptions clientDeleteOptions() { + return new ConcreteClientDeleteOptions(); + } + + /** + * Sets the collation. + * + * @param collation The collation. {@code null} represents the server default. + * @return {@code this}. + */ + ClientDeleteOptions collation(@Nullable Collation collation); + + /** + * Sets the index specification, + * {@code null}-ifies {@linkplain #hintString(String) hint string}. + * + * @param hint The index specification. {@code null} represents the server default. + * @return {@code this}. + */ + ClientDeleteOptions hint(@Nullable Bson hint); + + /** + * Sets the index name, + * {@code null}-ifies {@linkplain #hint(Bson) hint}. + * + * @param hintString The index name. {@code null} represents the server default. + * @return {@code this}. + */ + ClientDeleteOptions hintString(@Nullable String hintString); +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOptions.java new file mode 100644 index 00000000000..b6ad2c9c048 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOptions.java @@ -0,0 +1,73 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; +import com.mongodb.client.model.Collation; +import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * The options to apply when replacing documents. + * + * @since 5.3 + */ +@Sealed +public interface ClientReplaceOptions { + /** + * Creates the default options. + * + * @return The default options. + */ + static ClientReplaceOptions clientReplaceOptions() { + return new ConcreteClientReplaceOptions(); + } + + /** + * Sets the collation. + * + * @param collation The collation. {@code null} represents the server default. + * @return {@code this}. + */ + ClientReplaceOptions collation(@Nullable Collation collation); + + /** + * Sets the index specification, + * {@code null}-ifies {@linkplain #hintString(String) hint string}. + * + * @param hint The index specification. {@code null} represents the server default. + * @return {@code this}. + */ + ClientReplaceOptions hint(@Nullable Bson hint); + + /** + * Sets the index name, + * {@code null}-ifies {@linkplain #hint(Bson) hint}. + * + * @param hintString The index name. {@code null} represents the server default. + * @return {@code this}. + */ + ClientReplaceOptions hintString(@Nullable String hintString); + + /** + * Enables or disables creation of a document if no documents match the filter. + * + * @param upsert The upsert flag. {@code null} represents the server default. + * @return {@code this}. + */ + ClientReplaceOptions upsert(@Nullable Boolean upsert); +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOptions.java new file mode 100644 index 00000000000..4a74c8846e9 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOptions.java @@ -0,0 +1,83 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; +import com.mongodb.client.model.Collation; +import com.mongodb.client.model.Filters; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * The options to apply when updating documents. + * + * @since 5.3 + */ +@Sealed +public interface ClientUpdateOptions { + /** + * Creates the default options. + * + * @return The default options. + */ + static ClientUpdateOptions clientUpdateOptions() { + return new ConcreteClientUpdateOptions(); + } + + /** + * Sets the filters specifying to which array elements an update should apply. + * + * @param arrayFilters The array filters. {@code null} represents the server default. + * @return {@code this}. + * @see Filters + */ + ClientUpdateOptions arrayFilters(@Nullable Iterable arrayFilters); + + /** + * Sets the collation. + * + * @param collation The collation. {@code null} represents the server default. + * @return {@code this}. + */ + ClientUpdateOptions collation(@Nullable Collation collation); + + /** + * Sets the index specification, + * {@code null}-ifies {@linkplain #hintString(String) hint string}. + * + * @param hint The index specification. {@code null} represents the server default. + * @return {@code this}. + */ + ClientUpdateOptions hint(@Nullable Bson hint); + + /** + * Sets the index name, + * {@code null}-ifies {@linkplain #hint(Bson) hint}. + * + * @param hintString The index name. {@code null} represents the server default. + * @return {@code this}. + */ + ClientUpdateOptions hintString(@Nullable String hintString); + + /** + * Enables or disables creation of a document if no documents match the filter. + * + * @param upsert The upsert flag. {@code null} represents the server default. + * @return {@code this}. + */ + ClientUpdateOptions upsert(@Nullable Boolean upsert); +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java new file mode 100644 index 00000000000..48969e4d0d5 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java @@ -0,0 +1,369 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.annotations.Sealed; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Updates; +import com.mongodb.internal.client.model.bulk.ClientDeleteManyModel; +import com.mongodb.internal.client.model.bulk.ClientDeleteOneModel; +import com.mongodb.internal.client.model.bulk.ClientInsertOneModel; +import com.mongodb.internal.client.model.bulk.ClientReplaceOneModel; +import com.mongodb.internal.client.model.bulk.ClientUpdateManyModel; +import com.mongodb.internal.client.model.bulk.ClientUpdateOneModel; +import org.bson.Document; +import org.bson.conversions.Bson; + +import static com.mongodb.assertions.Assertions.notNull; + +/** + * An individual write operation to be executed as part of a client-level bulk write operation. + * + * @param The document type, for example {@link Document}. + * @since 5.3 + */ +// BULK-TODO I don't think T is needed +@Sealed +public interface ClientWriteModel { + /** + * Creates a model for inserting the {@code document} into the {@code namespace}. + * + * @param namespace The namespace. + * @param document The document. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientWriteModel insertOne( + final MongoNamespace namespace, + final T document) { + notNull("namespace", namespace); + notNull("document", document); + return new ClientInsertOneModel<>(namespace, document); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. + * This method is functionally equivalent to {@link #updateOne(MongoNamespace, Bson, Bson, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateOne( + final MongoNamespace namespace, + final Bson filter, + final Bson update) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + return new ClientUpdateOneModel<>(namespace, filter, update, null, null); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @param options The options. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateOne( + final MongoNamespace namespace, + final Bson filter, + final Bson update, + final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + notNull("options", options); + return new ClientUpdateOneModel<>(namespace, filter, update, null, options); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. + * This method is functionally equivalent to {@link #updateOne(MongoNamespace, Bson, Iterable, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateOne( + final MongoNamespace namespace, + final Bson filter, + final Iterable updatePipeline) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + return new ClientUpdateOneModel<>(namespace, filter, null, updatePipeline, null); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @param options The options. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateOne( + final MongoNamespace namespace, + final Bson filter, + final Iterable updatePipeline, + final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + notNull("options", options); + return new ClientUpdateOneModel<>(namespace, filter, null, updatePipeline, options); + } + + /** + * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. + * This method is functionally equivalent to {@link #updateMany(MongoNamespace, Bson, Bson, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateMany( + final MongoNamespace namespace, + final Bson filter, + final Bson update) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + return new ClientUpdateManyModel<>(namespace, filter, update, null, null); + } + + /** + * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @param options The options. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateMany( + final MongoNamespace namespace, + final Bson filter, + final Bson update, + final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + notNull("options", options); + return new ClientUpdateManyModel<>(namespace, filter, update, null, options); + } + + /** + * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. + * This method is functionally equivalent to {@link #updateMany(MongoNamespace, Bson, Iterable, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateMany( + final MongoNamespace namespace, + final Bson filter, + final Iterable updatePipeline) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + return new ClientUpdateManyModel<>(namespace, filter, null, updatePipeline, null); + } + + /** + * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @param options The options. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + * @see Updates + */ + static ClientWriteModel updateMany( + final MongoNamespace namespace, + final Bson filter, + final Iterable updatePipeline, + final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + notNull("options", options); + return new ClientUpdateManyModel<>(namespace, filter, null, updatePipeline, options); + } + + /** + * Creates a model for replacing at most one document in the {@code namespace} that matches the {@code filter}. + * This method is functionally equivalent to {@link #replaceOne(MongoNamespace, Bson, Object, ClientReplaceOptions)} + * with the {@linkplain ClientReplaceOptions#clientReplaceOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param replacement The replacement. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientWriteModel replaceOne( + final MongoNamespace namespace, + final Bson filter, + final T replacement) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("replacement", replacement); + return new ClientReplaceOneModel<>(namespace, filter, replacement, null); + } + + /** + * Creates a model for replacing at most one document in the {@code namespace} that matches the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param replacement The replacement. + * @param options The options. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientWriteModel replaceOne( + final MongoNamespace namespace, + final Bson filter, + final T replacement, + final ClientReplaceOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("replacement", replacement); + notNull("options", options); + return new ClientReplaceOneModel<>(namespace, filter, replacement, options); + } + + /** + * Creates a model for removing at most one document from the {@code namespace} that match the {@code filter}. + * This method is functionally equivalent to {@link #deleteOne(MongoNamespace, Bson, ClientDeleteOptions)} + * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientWriteModel deleteOne( + final MongoNamespace namespace, + final Bson filter) { + notNull("namespace", namespace); + notNull("filter", filter); + return new ClientDeleteOneModel<>(namespace, filter, null); + } + + /** + * Creates a model for removing at most one document from the {@code namespace} that match the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param options The options. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientWriteModel deleteOne( + final MongoNamespace namespace, + final Bson filter, + final ClientDeleteOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("options", options); + return new ClientDeleteOneModel<>(namespace, filter, options); + } + + /** + * Creates a model for removing all documents from the {@code namespace} that match the {@code filter}. + * This method is functionally equivalent to {@link #deleteMany(MongoNamespace, Bson, ClientDeleteOptions)} + * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientWriteModel deleteMany( + final MongoNamespace namespace, + final Bson filter) { + notNull("namespace", namespace); + notNull("filter", filter); + return new ClientDeleteManyModel<>(namespace, filter, null); + } + + /** + * Creates a model for removing all documents from the {@code namespace} that match the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param options The options. + * @return The requested model. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientWriteModel deleteMany( + final MongoNamespace namespace, + final Bson filter, + final ClientDeleteOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("options", options); + return new ClientDeleteManyModel<>(namespace, filter, options); + } +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/package-info.java b/driver-core/src/main/com/mongodb/client/model/bulk/package-info.java new file mode 100644 index 00000000000..309c0e4cfa6 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Models and options for the client-level bulk write operation. + */ +@NonNullApi +package com.mongodb.client.model.bulk; + +import com.mongodb.lang.NonNullApi; diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java new file mode 100644 index 00000000000..4388f793bb9 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java @@ -0,0 +1,141 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.result.bulk; + +import com.mongodb.ClientBulkWriteException; +import com.mongodb.WriteConcern; +import com.mongodb.annotations.Evolving; +import com.mongodb.bulk.WriteConcernError; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; + +import java.util.Map; + +/** + * The result of a successful or partially successful client-level bulk write operation. + * Note that if only some of the {@linkplain ClientWriteModel individual write operations} succeed, + * or if there are {@link WriteConcernError}s, then the successful partial result + * is still accessible via {@link ClientBulkWriteException#getPartialResult()}. + * + * @see ClientBulkWriteException + * @since 5.3 + */ +@Evolving +public interface ClientBulkWriteResult { + /** + * Indicated whether this result was {@linkplain WriteConcern#isAcknowledged() acknowledged}. + * If not, then all other methods throw {@link UnsupportedOperationException}. + * + * @return Whether this result was acknowledged. + */ + boolean isAcknowledged(); + + /** + * Indicates whether there are {@linkplain ClientBulkWriteOptions#verboseResults(Boolean) verbose results} + * of individual operations. + * If not, then {@link #getInsertResults()}, {@link #getUpdateResults()}, {@link #getDeleteResults()} + * throw {@link UnsupportedOperationException}. + * + * @return Whether there are verbose results. + * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. + */ + // BULK-TODO Do we still have getInsertedCount etc., when there are no verbose results? + boolean hasVerboseResults() throws UnsupportedOperationException; + + /** + * The number of documents that were inserted across all insert operations. + * + * @return The number of documents that were inserted. + * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. + */ + long getInsertedCount() throws UnsupportedOperationException; + + /** + * The number of documents that were upserted across all update and replace operations. + * + * @return The number of documents that were upserted. + * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. + */ + long getUpsertedCount() throws UnsupportedOperationException; + + /** + * The number of documents that matched the filters across all operations with filters. + * + * @return The number of documents that were matched. + * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. + */ + long getMatchedCount() throws UnsupportedOperationException; + + /** + * The number of documents that were modified across all update and replace operations. + * + * @return The number of documents that were modified. + * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. + */ + long getModifiedCount() throws UnsupportedOperationException; + + // BULK-TODO Is ReplaceOne reported as 1 modified (I expect this behavior), or 1 deleted and 1 inserted? + + /** + * The number of documents that were deleted across all delete operations. + * + * @return The number of documents that were deleted. + * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. + */ + long getDeletedCount() throws UnsupportedOperationException; + + /** + * The indexed {@link ClientInsertOneResult}s. + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * in the client-level bulk write operation. + *

+ * There are no guarantees on mutability or iteration order of the {@link Map} returned.

+ * + * @return The indexed {@link ClientInsertOneResult}s. + * @throws UnsupportedOperationException If this result is either not {@linkplain #isAcknowledged() acknowledged}, + * or does not have {@linkplain #hasVerboseResults() verbose results}. + * @see ClientBulkWriteException#getWriteErrors() + */ + Map getInsertResults() throws UnsupportedOperationException; + + /** + * The indexed {@link ClientUpdateResult}s. + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * in the client-level bulk write operation. + *

+ * There are no guarantees on mutability or iteration order of the {@link Map} returned.

+ * + * @return The indexed {@link ClientUpdateResult}s. + * @throws UnsupportedOperationException If this result is either not {@linkplain #isAcknowledged() acknowledged}, + * or does not have {@linkplain #hasVerboseResults() verbose results}. + * @see ClientBulkWriteException#getWriteErrors() + */ + Map getUpdateResults() throws UnsupportedOperationException; + + /** + * The indexed {@link ClientDeleteResult}s. + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * in the client-level bulk write operation. + *

+ * There are no guarantees on mutability or iteration order of the {@link Map} returned.

+ * + * @return The indexed {@link ClientDeleteResult}s. + * @throws UnsupportedOperationException If this result is either not {@linkplain #isAcknowledged() acknowledged}, + * or does not have {@linkplain #hasVerboseResults() verbose results}. + * @see ClientBulkWriteException#getWriteErrors() + */ + Map getDeleteResults() throws UnsupportedOperationException; +} diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientDeleteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientDeleteResult.java new file mode 100644 index 00000000000..8ac49725dbf --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientDeleteResult.java @@ -0,0 +1,36 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.result.bulk; + +import com.mongodb.annotations.Evolving; +import com.mongodb.bulk.WriteConcernError; +import com.mongodb.client.model.bulk.ClientWriteModel; + +/** + * The result of a successful {@linkplain ClientWriteModel individual delete operation}. + * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. + * + * @since 5.3 + */ +@Evolving +public interface ClientDeleteResult { + /** + * The number of documents that were deleted. + * + * @return The number of documents that were deleted. + */ + long getDeletedCount(); +} diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java new file mode 100644 index 00000000000..92f0d7d93fa --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java @@ -0,0 +1,37 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.result.bulk; + +import com.mongodb.annotations.Evolving; +import com.mongodb.bulk.WriteConcernError; +import com.mongodb.client.model.bulk.ClientWriteModel; +import org.bson.BsonValue; + +/** + * The result of a successful {@linkplain ClientWriteModel individual insert one operation}. + * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. + * + * @since 5.3 + */ +@Evolving +public interface ClientInsertOneResult { + /** + * The {@code "_id"} of the inserted document. + * + * @return The {@code "_id"} of the inserted document. + */ + BsonValue getInsertedId(); +} diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientUpdateResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientUpdateResult.java new file mode 100644 index 00000000000..af5e2e26fa8 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientUpdateResult.java @@ -0,0 +1,54 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.client.result.bulk; + +import com.mongodb.annotations.Evolving; +import com.mongodb.bulk.WriteConcernError; +import com.mongodb.client.model.bulk.ClientWriteModel; +import org.bson.BsonValue; + +import java.util.Optional; + +/** + * The result of a successful {@linkplain ClientWriteModel individual update or replace operation}. + * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. + * + * @since 5.3 + */ +@Evolving +public interface ClientUpdateResult { + /** + * The number of documents that matched the filter. + * + * @return The number of documents that matched the filter. + */ + long getMatchedCount(); + + /** + * The number of documents that were modified. + * + * @return The number of documents that were modified. + */ + long getModifiedCount(); + + /** + * The {@code "_id"} of the upserted document if and only if an upsert occurred. + * + * @return The {@code "_id"} of the upserted. + * {@linkplain Optional#isPresent() Present} if and only if an upsert occurred. + */ + Optional getUpsertedId(); +} diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/package-info.java b/driver-core/src/main/com/mongodb/client/result/bulk/package-info.java new file mode 100644 index 00000000000..744a2f1c055 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/result/bulk/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Results of the client-level bulk write operation. + */ +@NonNullApi +package com.mongodb.client.result.bulk; + +import com.mongodb.lang.NonNullApi; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java new file mode 100644 index 00000000000..d506045981d --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java @@ -0,0 +1,49 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientDeleteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ClientDeleteManyModel implements ClientWriteModel { + private final MongoNamespace namespace; + private final Bson filter; + private final ConcreteClientDeleteOptions options; + + public ClientDeleteManyModel( + final MongoNamespace namespace, + final Bson filter, + @Nullable final ClientDeleteOptions options) { + this.namespace = namespace; + this.filter = filter; + this.options = options == null ? ConcreteClientDeleteOptions.EMPTY : (ConcreteClientDeleteOptions) options; + } + + @Override + public String toString() { + return "ClientDeleteManyModel{" + + "namespace=" + namespace + + ", filter=" + filter + + ", options=" + options + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java new file mode 100644 index 00000000000..45a21d7d75a --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java @@ -0,0 +1,49 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientDeleteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ClientDeleteOneModel implements ClientWriteModel { + private final MongoNamespace namespace; + private final Bson filter; + private final ConcreteClientDeleteOptions options; + + public ClientDeleteOneModel( + final MongoNamespace namespace, + final Bson filter, + @Nullable final ClientDeleteOptions options) { + this.namespace = namespace; + this.filter = filter; + this.options = options == null ? ConcreteClientDeleteOptions.EMPTY : (ConcreteClientDeleteOptions) options; + } + + @Override + public String toString() { + return "ClientDeleteOneModel{" + + "namespace=" + namespace + + ", filter=" + filter + + ", options=" + options + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java new file mode 100644 index 00000000000..c7648a33325 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java @@ -0,0 +1,42 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientWriteModel; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ClientInsertOneModel implements ClientWriteModel { + private final MongoNamespace namespace; + private final T document; + + public ClientInsertOneModel( + final MongoNamespace namespace, + final T document) { + this.namespace = namespace; + this.document = document; + } + + @Override + public String toString() { + return "ClientInsertOneModel{" + + "namespace=" + namespace + + ", document=" + document + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java new file mode 100644 index 00000000000..8749c8cf161 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java @@ -0,0 +1,53 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientReplaceOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ClientReplaceOneModel implements ClientWriteModel { + private final MongoNamespace namespace; + private final Bson filter; + private final T replacement; + private final ConcreteClientReplaceOptions options; + + public ClientReplaceOneModel( + final MongoNamespace namespace, + final Bson filter, + final T replacement, + @Nullable final ClientReplaceOptions options) { + this.namespace = namespace; + this.filter = filter; + this.replacement = replacement; + this.options = options == null ? ConcreteClientReplaceOptions.EMPTY : (ConcreteClientReplaceOptions) options; + } + + @Override + public String toString() { + return "ClientReplaceOneModel{" + + "namespace=" + namespace + + ", filter=" + filter + + ", replacement=" + replacement + + ", options=" + options + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java new file mode 100644 index 00000000000..e723d7f6789 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientUpdateOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +import static com.mongodb.assertions.Assertions.assertTrue; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ClientUpdateManyModel implements ClientWriteModel { + private final MongoNamespace namespace; + private final Bson filter; + @Nullable + private final Bson update; + @Nullable + private final Iterable updatePipeline; + private final ConcreteClientUpdateOptions options; + + public ClientUpdateManyModel( + final MongoNamespace namespace, + final Bson filter, + @Nullable + final Bson update, + @Nullable + final Iterable updatePipeline, + @Nullable final ClientUpdateOptions options) { + this.namespace = namespace; + this.filter = filter; + assertTrue(update == null ^ updatePipeline == null); + this.update = update; + this.updatePipeline = updatePipeline; + this.options = options == null ? ConcreteClientUpdateOptions.EMPTY : (ConcreteClientUpdateOptions) options; + } + + @Override + public String toString() { + return "ClientUpdateManyModel{" + + "namespace=" + namespace + + ", filter=" + filter + + ", update=" + (update != null ? update : updatePipeline) + + ", options=" + options + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java new file mode 100644 index 00000000000..ea573e7d136 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientUpdateOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +import static com.mongodb.assertions.Assertions.assertTrue; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ClientUpdateOneModel implements ClientWriteModel { + private final MongoNamespace namespace; + private final Bson filter; + @Nullable + private final Bson update; + @Nullable + private final Iterable updatePipeline; + private final ConcreteClientUpdateOptions options; + + public ClientUpdateOneModel( + final MongoNamespace namespace, + final Bson filter, + @Nullable + final Bson update, + @Nullable + final Iterable updatePipeline, + @Nullable final ClientUpdateOptions options) { + this.namespace = namespace; + this.filter = filter; + assertTrue(update == null ^ updatePipeline == null); + this.update = update; + this.updatePipeline = updatePipeline; + this.options = options == null ? ConcreteClientUpdateOptions.EMPTY : (ConcreteClientUpdateOptions) options; + } + + @Override + public String toString() { + return "ClientUpdateOneModel{" + + "namespace=" + namespace + + ", filter=" + filter + + ", update=" + (update != null ? update : updatePipeline) + + ", options=" + options + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java new file mode 100644 index 00000000000..95492698522 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java @@ -0,0 +1,85 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.lang.Nullable; +import org.bson.BsonValue; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientBulkWriteOptions implements ClientBulkWriteOptions { + // BULK-TODO Introduce EMPTY similar to ConcreteClientUpdateOptions.EMPTY. + private static final Boolean CLIENT_DEFAULT_ORDERED = true; + private static final Boolean CLIENT_DEFAULT_VERBOSE_RESULTS = false; + + @Nullable + private Boolean ordered; + @Nullable + private Boolean bypassDocumentValidation; + @Nullable + private Bson let; + @Nullable + private BsonValue comment; + @Nullable + private Boolean verboseResults; + + public ConcreteClientBulkWriteOptions() { + } + + @Override + public ClientBulkWriteOptions ordered(@Nullable final Boolean ordered) { + this.ordered = ordered; + return this; + } + + @Override + public ClientBulkWriteOptions bypassDocumentValidation(@Nullable final Boolean bypassDocumentValidation) { + this.bypassDocumentValidation = bypassDocumentValidation; + return this; + } + + @Override + public ClientBulkWriteOptions let(@Nullable final Bson let) { + this.let = let; + return this; + } + + @Override + public ClientBulkWriteOptions comment(@Nullable final BsonValue comment) { + this.comment = comment; + return this; + } + + @Override + public ClientBulkWriteOptions verboseResults(@Nullable final Boolean verboseResults) { + this.verboseResults = verboseResults; + return this; + } + + @Override + public String toString() { + return "ClientBulkWriteOptions{" + + "ordered=" + ordered + + ", bypassDocumentValidation=" + bypassDocumentValidation + + ", let=" + let + + ", comment=" + comment + + ", verboseResults=" + verboseResults + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java new file mode 100644 index 00000000000..18215ad4592 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java @@ -0,0 +1,67 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.client.model.Collation; +import com.mongodb.client.model.bulk.ClientDeleteOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientDeleteOptions implements ClientDeleteOptions { + static final ConcreteClientDeleteOptions EMPTY = new ConcreteClientDeleteOptions(); + + @Nullable + private Collation collation; + @Nullable + private Bson hint; + @Nullable + private String hintString; + + public ConcreteClientDeleteOptions() { + } + + @Override + public ClientDeleteOptions collation(@Nullable final Collation collation) { + this.collation = collation; + return this; + } + + @Override + public ClientDeleteOptions hint(@Nullable final Bson hint) { + this.hint = hint; + this.hintString = null; + return this; + } + + @Override + public ClientDeleteOptions hintString(@Nullable final String hintString) { + this.hintString = hintString; + this.hint = null; + return this; + } + + @Override + public String toString() { + return "ClientDeleteOptions{" + + "collation=" + collation + + ", hint=" + hint + + ", hintString='" + hintString + '\'' + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java new file mode 100644 index 00000000000..963fee20614 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.client.model.Collation; +import com.mongodb.client.model.bulk.ClientReplaceOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientReplaceOptions implements ClientReplaceOptions { + static final ConcreteClientReplaceOptions EMPTY = new ConcreteClientReplaceOptions(); + + @Nullable + private Collation collation; + @Nullable + private Bson hint; + @Nullable + private String hintString; + @Nullable + private Boolean upsert; + + public ConcreteClientReplaceOptions() { + } + + @Override + public ClientReplaceOptions collation(@Nullable final Collation collation) { + this.collation = collation; + return this; + } + + @Override + public ClientReplaceOptions hint(@Nullable final Bson hint) { + this.hint = hint; + this.hintString = null; + return this; + } + + @Override + public ClientReplaceOptions hintString(@Nullable final String hintString) { + this.hintString = hintString; + this.hint = null; + return this; + } + + @Override + public ClientReplaceOptions upsert(@Nullable final Boolean upsert) { + this.upsert = upsert; + return this; + } + + @Override + public String toString() { + return "ClientReplaceOptions{" + + "collation=" + collation + + ", hint=" + hint + + ", hintString='" + hintString + '\'' + + ", upsert=" + upsert + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java new file mode 100644 index 00000000000..3d7c13cdd3b --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java @@ -0,0 +1,85 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.client.model.Collation; +import com.mongodb.client.model.bulk.ClientUpdateOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientUpdateOptions implements ClientUpdateOptions { + static final ConcreteClientUpdateOptions EMPTY = new ConcreteClientUpdateOptions(); + + @Nullable + private Iterable arrayFilters; + @Nullable + private Collation collation; + @Nullable + private Bson hint; + @Nullable + private String hintString; + @Nullable + private Boolean upsert; + + public ConcreteClientUpdateOptions() { + } + + @Override + public ClientUpdateOptions arrayFilters(@Nullable final Iterable arrayFilters) { + this.arrayFilters = arrayFilters; + return this; + } + + @Override + public ClientUpdateOptions collation(@Nullable final Collation collation) { + this.collation = collation; + return this; + } + + @Override + public ClientUpdateOptions hint(@Nullable final Bson hint) { + this.hint = hint; + this.hintString = null; + return this; + } + + @Override + public ClientUpdateOptions hintString(@Nullable final String hintString) { + this.hintString = hintString; + this.hint = null; + return this; + } + + @Override + public ClientUpdateOptions upsert(@Nullable final Boolean upsert) { + this.upsert = upsert; + return this; + } + + @Override + public String toString() { + return "ClientUpdateOptions{" + + "arrayFilters=" + arrayFilters + + ", collation=" + collation + + ", hint=" + hint + + ", hintString='" + hintString + '\'' + + ", upsert=" + upsert + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/package-info.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/package-info.java new file mode 100644 index 00000000000..2d66f44646b --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal program elements related to {@link com.mongodb.client.model.bulk}. + */ +@NonNullApi +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.lang.NonNullApi; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java new file mode 100644 index 00000000000..0123d3509e2 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java @@ -0,0 +1,134 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.result.bulk; + +import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.result.bulk.ClientDeleteResult; +import com.mongodb.client.result.bulk.ClientInsertOneResult; +import com.mongodb.client.result.bulk.ClientUpdateResult; + +import java.util.Map; +import java.util.Objects; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class AcknowledgedSummaryClientBulkWriteResult implements ClientBulkWriteResult { + private final long insertedCount; + private final long upsertedCount; + private final long matchedCount; + private final long modifiedCount; + private final long deletedCount; + + public AcknowledgedSummaryClientBulkWriteResult( + final long insertedCount, + final long upsertedCount, + final long matchedCount, + final long modifiedCount, + final long deletedCount) { + this.insertedCount = insertedCount; + this.upsertedCount = upsertedCount; + this.matchedCount = matchedCount; + this.modifiedCount = modifiedCount; + this.deletedCount = deletedCount; + } + + @Override + public boolean isAcknowledged() { + return true; + } + + @Override + public boolean hasVerboseResults() { + return false; + } + + @Override + public long getInsertedCount() { + return insertedCount; + } + + @Override + public long getUpsertedCount() { + return upsertedCount; + } + + @Override + public long getMatchedCount() { + return matchedCount; + } + + @Override + public long getModifiedCount() { + return modifiedCount; + } + + @Override + public long getDeletedCount() { + return deletedCount; + } + + @Override + public Map getInsertResults() throws UnsupportedOperationException { + throw noVerboseResultsException(); + } + + @Override + public Map getUpdateResults() throws UnsupportedOperationException { + throw noVerboseResultsException(); + } + + @Override + public Map getDeleteResults() throws UnsupportedOperationException { + throw noVerboseResultsException(); + } + + private static UnsupportedOperationException noVerboseResultsException() { + return new UnsupportedOperationException("Verbose results are not available"); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final AcknowledgedSummaryClientBulkWriteResult that = (AcknowledgedSummaryClientBulkWriteResult) o; + return insertedCount == that.insertedCount + && upsertedCount == that.upsertedCount + && matchedCount == that.matchedCount + && modifiedCount == that.modifiedCount + && deletedCount == that.deletedCount; + } + + @Override + public int hashCode() { + return Objects.hash(insertedCount, upsertedCount, matchedCount, modifiedCount, deletedCount); + } + + @Override + public String toString() { + return "AcknowledgedSummaryClientBulkWriteResult{" + + "insertedCount=" + insertedCount + + ", upsertedCount=" + upsertedCount + + ", matchedCount=" + matchedCount + + ", modifiedCount=" + modifiedCount + + ", deletedCount=" + deletedCount + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java new file mode 100644 index 00000000000..75e8650e5b3 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -0,0 +1,133 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.result.bulk; + +import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.result.bulk.ClientDeleteResult; +import com.mongodb.client.result.bulk.ClientInsertOneResult; +import com.mongodb.client.result.bulk.ClientUpdateResult; +import com.mongodb.lang.Nullable; + +import java.util.Map; +import java.util.Objects; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.unmodifiableMap; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class AcknowledgedVerboseClientBulkWriteResult implements ClientBulkWriteResult { + private final AcknowledgedSummaryClientBulkWriteResult summaryResults; + private final Map insertResults; + private final Map updateResults; + private final Map deleteResults; + + public AcknowledgedVerboseClientBulkWriteResult( + final AcknowledgedSummaryClientBulkWriteResult summaryResults, + @Nullable final Map insertResults, + @Nullable final Map updateResults, + @Nullable final Map deleteResults) { + this.summaryResults = summaryResults; + this.insertResults = insertResults == null ? emptyMap() : unmodifiableMap(insertResults); + this.updateResults = updateResults == null ? emptyMap() : unmodifiableMap(updateResults); + this.deleteResults = deleteResults == null ? emptyMap() : unmodifiableMap(deleteResults); + } + + @Override + public boolean isAcknowledged() { + return true; + } + + @Override + public boolean hasVerboseResults() { + return true; + } + + @Override + public long getInsertedCount() { + return summaryResults.getInsertedCount(); + } + + @Override + public long getUpsertedCount() { + return summaryResults.getUpsertedCount(); + } + + @Override + public long getMatchedCount() { + return summaryResults.getMatchedCount(); + } + + @Override + public long getModifiedCount() { + return summaryResults.getModifiedCount(); + } + + @Override + public long getDeletedCount() { + return summaryResults.getDeletedCount(); + } + + @Override + public Map getInsertResults() { + return insertResults; + } + + @Override + public Map getUpdateResults() { + return updateResults; + } + + @Override + public Map getDeleteResults() { + return deleteResults; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final AcknowledgedVerboseClientBulkWriteResult that = (AcknowledgedVerboseClientBulkWriteResult) o; + return Objects.equals(summaryResults, that.summaryResults) + && Objects.equals(insertResults, that.insertResults) + && Objects.equals(updateResults, that.updateResults) + && Objects.equals(deleteResults, that.deleteResults); + } + + @Override + public int hashCode() { + return Objects.hash(summaryResults, insertResults, updateResults, deleteResults); + } + + @Override + public String toString() { + return "AcknowledgedVerboseClientBulkWriteResult{" + + "insertedCount=" + summaryResults.getInsertedCount() + + ", upsertedCount=" + summaryResults.getUpsertedCount() + + ", matchedCount=" + summaryResults.getMatchedCount() + + ", modifiedCount=" + summaryResults.getModifiedCount() + + ", deletedCount=" + summaryResults.getDeletedCount() + + ", insertResults=" + insertResults + + ", updateResults=" + updateResults + + ", deleteResults=" + deleteResults + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java new file mode 100644 index 00000000000..e94b442d390 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.result.bulk; + +import com.mongodb.client.result.bulk.ClientDeleteResult; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientDeleteResult implements ClientDeleteResult { + private final long deletedCount; + + public ConcreteClientDeleteResult(final long deletedCount) { + this.deletedCount = deletedCount; + } + + @Override + public long getDeletedCount() { + return deletedCount; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final ConcreteClientDeleteResult that = (ConcreteClientDeleteResult) o; + return deletedCount == that.deletedCount; + } + + @Override + public int hashCode() { + return Long.hashCode(deletedCount); + } + + @Override + public String toString() { + return "ClientDeleteResult{" + + "deletedCount=" + deletedCount + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java new file mode 100644 index 00000000000..c1cdb9843ac --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java @@ -0,0 +1,61 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.result.bulk; + +import com.mongodb.client.result.bulk.ClientInsertOneResult; +import org.bson.BsonValue; + +import java.util.Objects; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientInsertOneResult implements ClientInsertOneResult { + private final BsonValue insertedId; + + public ConcreteClientInsertOneResult(final BsonValue insertedId) { + this.insertedId = insertedId; + } + + @Override + public BsonValue getInsertedId() { + return insertedId; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final ConcreteClientInsertOneResult that = (ConcreteClientInsertOneResult) o; + return Objects.equals(insertedId, that.insertedId); + } + + @Override + public int hashCode() { + return Objects.hashCode(insertedId); + } + + @Override + public String toString() { + return "ClientInsertOneResult{" + + "insertedId=" + insertedId + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java new file mode 100644 index 00000000000..7b3e8b36e9d --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java @@ -0,0 +1,87 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.result.bulk; + +import com.mongodb.client.result.bulk.ClientUpdateResult; +import com.mongodb.lang.Nullable; +import org.bson.BsonValue; + +import java.util.Objects; +import java.util.Optional; + +import static java.util.Optional.ofNullable; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientUpdateResult implements ClientUpdateResult { + private final long matchedCount; + private final long modifiedCount; + @Nullable + private final BsonValue upsertedId; + + public ConcreteClientUpdateResult( + final long matchedCount, + final long modifiedCount, + @Nullable final BsonValue upsertedId) { + this.matchedCount = matchedCount; + this.modifiedCount = modifiedCount; + this.upsertedId = upsertedId; + } + + @Override + public long getMatchedCount() { + return matchedCount; + } + + @Override + public long getModifiedCount() { + return modifiedCount; + } + + @Override + public Optional getUpsertedId() { + return ofNullable(upsertedId); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final ConcreteClientUpdateResult that = (ConcreteClientUpdateResult) o; + return matchedCount == that.matchedCount + && modifiedCount == that.modifiedCount + && Objects.equals(upsertedId, that.upsertedId); + } + + @Override + public int hashCode() { + return Objects.hash(matchedCount, modifiedCount, upsertedId); + } + + @Override + public String toString() { + return "ClientUpdateResult{" + + "matchedCount=" + matchedCount + + ", modifiedCount=" + modifiedCount + + ", upsertedId=" + upsertedId + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java new file mode 100644 index 00000000000..dd508169dee --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java @@ -0,0 +1,92 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.result.bulk; + +import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.result.bulk.ClientDeleteResult; +import com.mongodb.client.result.bulk.ClientInsertOneResult; +import com.mongodb.client.result.bulk.ClientUpdateResult; + +import java.util.Map; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class UnacknowledgedClientBulkWriteResult implements ClientBulkWriteResult { + public static final UnacknowledgedClientBulkWriteResult INSTANCE = new UnacknowledgedClientBulkWriteResult(); + + private UnacknowledgedClientBulkWriteResult() { + } + + @Override + public boolean isAcknowledged() { + return false; + } + + @Override + public boolean hasVerboseResults() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public long getInsertedCount() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public long getUpsertedCount() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public long getMatchedCount() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public long getModifiedCount() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public long getDeletedCount() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public Map getInsertResults() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public Map getUpdateResults() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + @Override + public Map getDeleteResults() throws UnsupportedOperationException { + throw createUnacknowledgedResultsException(); + } + + private static UnsupportedOperationException createUnacknowledgedResultsException() { + return new UnsupportedOperationException("Cannot get information about an unacknowledged write"); + } + + @Override + public String toString() { + return "UnacknowledgedClientBulkWriteResult{}"; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java new file mode 100644 index 00000000000..d3dfae86619 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal program elements related to {@link com.mongodb.client.result.bulk}. + */ +@NonNullApi +package com.mongodb.internal.client.result.bulk; + +import com.mongodb.lang.NonNullApi; diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt index 42313ed2b13..c7a1fd65fc5 100644 --- a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt @@ -25,6 +25,9 @@ import com.mongodb.client.ListDatabasesIterable import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable +import com.mongodb.client.model.bulk.ClientBulkWriteOptions +import com.mongodb.client.model.bulk.ClientWriteModel +import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.coroutine.MongoCluster import java.util.concurrent.TimeUnit import kotlinx.coroutines.runBlocking @@ -111,5 +114,37 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) + override fun bulkWrite( + models: MutableList>, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + + override fun bulkWrite( + models: MutableList>, + options: ClientBulkWriteOptions, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + + override fun bulkWrite( + clientSession: ClientSession, + models: MutableList>, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + + override fun bulkWrite( + clientSession: ClientSession, + models: MutableList>, + options: ClientBulkWriteOptions, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + private fun ClientSession.unwrapped() = (this as SyncClientSession).wrapped } diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt index 7b948fa6d1d..2c7f87cceeb 100644 --- a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt @@ -25,6 +25,9 @@ import com.mongodb.client.ListDatabasesIterable import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable +import com.mongodb.client.model.bulk.ClientBulkWriteOptions +import com.mongodb.client.model.bulk.ClientWriteModel +import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.MongoCluster import java.util.concurrent.TimeUnit import org.bson.Document @@ -110,5 +113,37 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) + override fun bulkWrite( + models: MutableList>, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + + override fun bulkWrite( + models: MutableList>, + options: ClientBulkWriteOptions, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + + override fun bulkWrite( + clientSession: ClientSession, + models: MutableList>, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + + override fun bulkWrite( + clientSession: ClientSession, + models: MutableList>, + options: ClientBulkWriteOptions, + documentClass: Class + ): ClientBulkWriteResult { + TODO("BULK-TODO implement") + } + private fun ClientSession.unwrapped() = (this as SyncClientSession).wrapped } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java index ceb5ea72769..b8f7f37c42c 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java @@ -16,6 +16,7 @@ package com.mongodb.reactivestreams.client.syncadapter; +import com.mongodb.ClientBulkWriteException; import com.mongodb.ClientSessionOptions; import com.mongodb.ReadConcern; import com.mongodb.ReadPreference; @@ -27,6 +28,9 @@ import com.mongodb.client.MongoCluster; import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.reactivestreams.client.internal.BatchCursor; import org.bson.Document; @@ -274,6 +278,38 @@ public void close() { } + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels, tDocumentClass); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels, options, tDocumentClass); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels, tDocumentClass); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels, options, tDocumentClass); + } + @Override public ClusterDescription getClusterDescription() { return wrapped.getClusterDescription(); diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java index 780f7260eb4..7d83b825ee2 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java @@ -16,16 +16,21 @@ package com.mongodb.reactivestreams.client.syncadapter; +import com.mongodb.ClientBulkWriteException; import com.mongodb.ClientSessionOptions; import com.mongodb.ReadConcern; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; +import com.mongodb.assertions.Assertions; import com.mongodb.client.ChangeStreamIterable; import com.mongodb.client.ClientSession; import com.mongodb.client.ListDatabasesIterable; import com.mongodb.client.MongoCluster; import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; import org.bson.BsonDocument; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; @@ -278,6 +283,38 @@ public ChangeStreamIterable watch(final ClientSession clientS return new SyncChangeStreamIterable<>(wrapped.watch(unwrap(clientSession), pipeline, resultClass)); } + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + throw Assertions.fail("BULK-TODO implement"); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + throw Assertions.fail("BULK-TODO implement"); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + throw Assertions.fail("BULK-TODO implement"); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + throw Assertions.fail("BULK-TODO implement"); + } + private com.mongodb.reactivestreams.client.ClientSession unwrap(final ClientSession clientSession) { return ((SyncClientSession) clientSession).getWrapped(); } diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala index 3871aded144..15f6b5ad387 100644 --- a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala +++ b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala @@ -1,5 +1,8 @@ package org.mongodb.scala.syncadapter +import com.mongodb.assertions.Assertions +import com.mongodb.client.model.bulk.{ ClientBulkWriteOptions, ClientWriteModel } +import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.{ ClientSessionOptions, ReadConcern, ReadPreference, WriteConcern } import com.mongodb.client.{ ClientSession, MongoCluster => JMongoCluster, MongoDatabase => JMongoDatabase } import org.bson.Document @@ -8,6 +11,7 @@ import org.bson.conversions.Bson import org.mongodb.scala.MongoCluster import org.mongodb.scala.bson.DefaultHelper.DefaultsTo +import java.util import java.util.concurrent.TimeUnit import scala.collection.JavaConverters._ import scala.concurrent.Await @@ -123,4 +127,32 @@ class SyncMongoCluster(wrapped: MongoCluster) extends JMongoCluster { private def unwrap(clientSession: ClientSession): org.mongodb.scala.ClientSession = clientSession.asInstanceOf[SyncClientSession].wrapped + + override def bulkWrite[TDocument]( + models: util.List[_ <: ClientWriteModel[_ <: TDocument]], + documentClass: Class[TDocument] + ): ClientBulkWriteResult = + throw Assertions.fail("BULK-TODO implement") + + override def bulkWrite[TDocument]( + models: util.List[_ <: ClientWriteModel[_ <: TDocument]], + options: ClientBulkWriteOptions, + documentClass: Class[TDocument] + ): ClientBulkWriteResult = + throw Assertions.fail("BULK-TODO implement") + + override def bulkWrite[TDocument]( + clientSession: ClientSession, + models: util.List[_ <: ClientWriteModel[_ <: TDocument]], + documentClass: Class[TDocument] + ): ClientBulkWriteResult = + throw Assertions.fail("BULK-TODO implement") + + override def bulkWrite[TDocument]( + clientSession: ClientSession, + models: util.List[_ <: ClientWriteModel[_ <: TDocument]], + options: ClientBulkWriteOptions, + documentClass: Class[TDocument] + ): ClientBulkWriteResult = + throw Assertions.fail("BULK-TODO implement") } diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index f901845333b..baffe62009d 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -16,7 +16,9 @@ package com.mongodb.client; +import com.mongodb.ClientBulkWriteException; import com.mongodb.ClientSessionOptions; +import com.mongodb.MongoException; import com.mongodb.MongoNamespace; import com.mongodb.ReadConcern; import com.mongodb.ReadPreference; @@ -24,6 +26,9 @@ import com.mongodb.annotations.Alpha; import com.mongodb.annotations.Immutable; import com.mongodb.annotations.Reason; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.lang.Nullable; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; @@ -352,4 +357,96 @@ public interface MongoCluster { * @mongodb.driver.dochub core/changestreams Change Streams */ ChangeStreamIterable watch(ClientSession clientSession, List pipeline, Class resultClass); + + /** + * Executes a client-level bulk write operation. + * This method is functionally equivalent to {@link #bulkWrite(List, ClientBulkWriteOptions, Class)} + * with the {@linkplain ClientBulkWriteOptions#clientBulkWriteOptions() default options}. + * + * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param documentClass The document class. + * @return The {@link ClientBulkWriteResult} if the operation is successful. + * @param The document type, for example {@link Document}. + * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, + * and there is at least one of the following pieces of information to report: + * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, + * {@link ClientBulkWriteException#getPartialResult()}. + * @throws MongoException Only if the operation is unsuccessful. + * @since 5.3 + * @mongodb.server.release 8.0 + * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite + */ + ClientBulkWriteResult bulkWrite( + List> models, + Class documentClass) throws ClientBulkWriteException; + + /** + * Executes a client-level bulk write operation. + * + * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param options The options. + * @param documentClass The document class. + * @return The {@link ClientBulkWriteResult} if the operation is successful. + * @param The document type, for example {@link Document}. + * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, + * and there is at least one of the following pieces of information to report: + * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, + * {@link ClientBulkWriteException#getPartialResult()}. + * @throws MongoException Only if the operation is unsuccessful. + * @since 5.3 + * @mongodb.server.release 8.0 + * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite + */ + ClientBulkWriteResult bulkWrite( + List> models, + ClientBulkWriteOptions options, + Class documentClass) throws ClientBulkWriteException; + + /** + * Executes a client-level bulk write operation. + * This method is functionally equivalent to {@link #bulkWrite(ClientSession, List, ClientBulkWriteOptions, Class)} + * with the {@linkplain ClientBulkWriteOptions#clientBulkWriteOptions() default options}. + * + * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. + * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param documentClass The document class. + * @return The {@link ClientBulkWriteResult} if the operation is successful. + * @param The document type, for example {@link Document}. + * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, + * and there is at least one of the following pieces of information to report: + * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, + * {@link ClientBulkWriteException#getPartialResult()}. + * @throws MongoException Only if the operation is unsuccessful. + * @since 5.3 + * @mongodb.server.release 8.0 + * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite + */ + ClientBulkWriteResult bulkWrite( + ClientSession clientSession, + List> models, + Class documentClass) throws ClientBulkWriteException; + + /** + * Executes a client-level bulk write operation. + * + * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. + * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param options The options. + * @param documentClass The document class. + * @return The {@link ClientBulkWriteResult} if the operation is successful. + * @param The document type, for example {@link Document}. + * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, + * and there is at least one of the following pieces of information to report: + * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, + * {@link ClientBulkWriteException#getPartialResult()}. + * @throws MongoException Only if the operation is unsuccessful. + * @since 5.3 + * @mongodb.server.release 8.0 + * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite + */ + ClientBulkWriteResult bulkWrite( + ClientSession clientSession, + List> models, + ClientBulkWriteOptions options, + Class documentClass) throws ClientBulkWriteException; } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java index 473d8ec4e8e..4ece29fd18a 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java @@ -17,6 +17,7 @@ package com.mongodb.client.internal; import com.mongodb.AutoEncryptionSettings; +import com.mongodb.ClientBulkWriteException; import com.mongodb.ClientSessionOptions; import com.mongodb.MongoClientSettings; import com.mongodb.MongoDriverInformation; @@ -31,6 +32,9 @@ import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; import com.mongodb.client.SynchronousContextProvider; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.connection.SocketSettings; import com.mongodb.connection.TransportSettings; @@ -256,6 +260,38 @@ public ChangeStreamIterable watch( return delegate.watch(clientSession, pipeline, resultClass); } + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels, tDocumentClass); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels, options, tDocumentClass); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels, tDocumentClass); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels, options, tDocumentClass); + } + private static Cluster createCluster(final MongoClientSettings settings, @Nullable final MongoDriverInformation mongoDriverInformation) { notNull("settings", settings); diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index b3d03095070..18cd27174f2 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -17,6 +17,7 @@ package com.mongodb.client.internal; import com.mongodb.AutoEncryptionSettings; +import com.mongodb.ClientBulkWriteException; import com.mongodb.ClientSessionOptions; import com.mongodb.MongoClientException; import com.mongodb.MongoException; @@ -30,6 +31,7 @@ import com.mongodb.ServerApi; import com.mongodb.TransactionOptions; import com.mongodb.WriteConcern; +import com.mongodb.assertions.Assertions; import com.mongodb.client.ChangeStreamIterable; import com.mongodb.client.ClientSession; import com.mongodb.client.ListDatabasesIterable; @@ -37,6 +39,9 @@ import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; import com.mongodb.client.SynchronousContextProvider; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.internal.IgnorableRequestContext; import com.mongodb.internal.TimeoutSettings; import com.mongodb.internal.binding.ClusterAwareReadWriteBinding; @@ -307,6 +312,50 @@ public ChangeStreamIterable watch(final ClientSession clientS return createChangeStreamIterable(clientSession, pipeline, clazz); } + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + notNull("clientWriteModels", clientWriteModels); + notNull("tDocumentClass", tDocumentClass); + throw Assertions.fail("BULK-TODO implement"); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + notNull("clientWriteModels", clientWriteModels); + notNull("options", options); + notNull("tDocumentClass", tDocumentClass); + throw Assertions.fail("BULK-TODO implement"); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final Class tDocumentClass) throws ClientBulkWriteException { + notNull("clientSession", clientSession); + notNull("clientWriteModels", clientWriteModels); + notNull("tDocumentClass", tDocumentClass); + throw Assertions.fail("BULK-TODO implement"); + } + + @Override + public ClientBulkWriteResult bulkWrite( + final ClientSession clientSession, + final List> clientWriteModels, + final ClientBulkWriteOptions options, + final Class tDocumentClass) throws ClientBulkWriteException { + notNull("clientSession", clientSession); + notNull("clientWriteModels", clientWriteModels); + notNull("options", options); + notNull("tDocumentClass", tDocumentClass); + throw Assertions.fail("BULK-TODO implement"); + } + private ListDatabasesIterable createListDatabasesIterable(@Nullable final ClientSession clientSession, final Class clazz) { return new ListDatabasesIterableImpl<>(clientSession, clazz, codecRegistry, ReadPreference.primary(), operationExecutor, retryReads, timeoutSettings); } From af854edb75e3787e3e10d4fda800ca07e6d97a08 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 23 Jul 2024 14:49:54 -0600 Subject: [PATCH 02/59] Remove the type parameter from `ClientWriteModel` JAVA-5527 --- .../client/model/bulk/ClientWriteModel.java | 88 ++++++++----------- .../model/bulk/ClientDeleteManyModel.java | 2 +- .../model/bulk/ClientDeleteOneModel.java | 2 +- .../model/bulk/ClientInsertOneModel.java | 6 +- .../model/bulk/ClientReplaceOneModel.java | 6 +- .../model/bulk/ClientUpdateManyModel.java | 2 +- .../model/bulk/ClientUpdateOneModel.java | 2 +- .../coroutine/syncadapter/SyncMongoCluster.kt | 24 ++--- .../client/syncadapter/SyncMongoCluster.kt | 24 ++--- .../client/syncadapter/SyncMongoClient.java | 32 +++---- .../client/syncadapter/SyncMongoCluster.java | 24 +++-- .../scala/syncadapter/SyncMongoCluster.scala | 24 +++-- .../main/com/mongodb/client/MongoCluster.java | 35 +++----- .../client/internal/MongoClientImpl.java | 32 +++---- .../client/internal/MongoClusterImpl.java | 28 +++--- 15 files changed, 134 insertions(+), 197 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java index 48969e4d0d5..683fce6f5a4 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java @@ -33,27 +33,25 @@ /** * An individual write operation to be executed as part of a client-level bulk write operation. * - * @param The document type, for example {@link Document}. * @since 5.3 */ -// BULK-TODO I don't think T is needed @Sealed -public interface ClientWriteModel { +public interface ClientWriteModel { /** * Creates a model for inserting the {@code document} into the {@code namespace}. * * @param namespace The namespace. * @param document The document. * @return The requested model. - * @param The document type, for example {@link Document}. + * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel insertOne( + static ClientWriteModel insertOne( final MongoNamespace namespace, - final T document) { + final TDocument document) { notNull("namespace", namespace); notNull("document", document); - return new ClientInsertOneModel<>(namespace, document); + return new ClientInsertOneModel(namespace, document); } /** @@ -65,18 +63,17 @@ static ClientWriteModel insertOne( * @param filter The filter. * @param update The update. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateOne( + static ClientWriteModel updateOne( final MongoNamespace namespace, final Bson filter, final Bson update) { notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); - return new ClientUpdateOneModel<>(namespace, filter, update, null, null); + return new ClientUpdateOneModel(namespace, filter, update, null, null); } /** @@ -87,11 +84,10 @@ static ClientWriteModel updateOne( * @param update The update. * @param options The options. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateOne( + static ClientWriteModel updateOne( final MongoNamespace namespace, final Bson filter, final Bson update, @@ -100,7 +96,7 @@ static ClientWriteModel updateOne( notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ClientUpdateOneModel<>(namespace, filter, update, null, options); + return new ClientUpdateOneModel(namespace, filter, update, null, options); } /** @@ -112,18 +108,17 @@ static ClientWriteModel updateOne( * @param filter The filter. * @param updatePipeline The update pipeline. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateOne( + static ClientWriteModel updateOne( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ClientUpdateOneModel<>(namespace, filter, null, updatePipeline, null); + return new ClientUpdateOneModel(namespace, filter, null, updatePipeline, null); } /** @@ -134,11 +129,10 @@ static ClientWriteModel updateOne( * @param updatePipeline The update pipeline. * @param options The options. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateOne( + static ClientWriteModel updateOne( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, @@ -147,7 +141,7 @@ static ClientWriteModel updateOne( notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ClientUpdateOneModel<>(namespace, filter, null, updatePipeline, options); + return new ClientUpdateOneModel(namespace, filter, null, updatePipeline, options); } /** @@ -159,18 +153,17 @@ static ClientWriteModel updateOne( * @param filter The filter. * @param update The update. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateMany( + static ClientWriteModel updateMany( final MongoNamespace namespace, final Bson filter, final Bson update) { notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); - return new ClientUpdateManyModel<>(namespace, filter, update, null, null); + return new ClientUpdateManyModel(namespace, filter, update, null, null); } /** @@ -181,11 +174,10 @@ static ClientWriteModel updateMany( * @param update The update. * @param options The options. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateMany( + static ClientWriteModel updateMany( final MongoNamespace namespace, final Bson filter, final Bson update, @@ -194,7 +186,7 @@ static ClientWriteModel updateMany( notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ClientUpdateManyModel<>(namespace, filter, update, null, options); + return new ClientUpdateManyModel(namespace, filter, update, null, options); } /** @@ -206,18 +198,17 @@ static ClientWriteModel updateMany( * @param filter The filter. * @param updatePipeline The update pipeline. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateMany( + static ClientWriteModel updateMany( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ClientUpdateManyModel<>(namespace, filter, null, updatePipeline, null); + return new ClientUpdateManyModel(namespace, filter, null, updatePipeline, null); } /** @@ -228,11 +219,10 @@ static ClientWriteModel updateMany( * @param updatePipeline The update pipeline. * @param options The options. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters * @see Updates */ - static ClientWriteModel updateMany( + static ClientWriteModel updateMany( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, @@ -241,7 +231,7 @@ static ClientWriteModel updateMany( notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ClientUpdateManyModel<>(namespace, filter, null, updatePipeline, options); + return new ClientUpdateManyModel(namespace, filter, null, updatePipeline, options); } /** @@ -253,17 +243,17 @@ static ClientWriteModel updateMany( * @param filter The filter. * @param replacement The replacement. * @return The requested model. - * @param The document type, for example {@link Document}. + * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel replaceOne( + static ClientWriteModel replaceOne( final MongoNamespace namespace, final Bson filter, - final T replacement) { + final TDocument replacement) { notNull("namespace", namespace); notNull("filter", filter); notNull("replacement", replacement); - return new ClientReplaceOneModel<>(namespace, filter, replacement, null); + return new ClientReplaceOneModel(namespace, filter, replacement, null); } /** @@ -274,19 +264,19 @@ static ClientWriteModel replaceOne( * @param replacement The replacement. * @param options The options. * @return The requested model. - * @param The document type, for example {@link Document}. + * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel replaceOne( + static ClientWriteModel replaceOne( final MongoNamespace namespace, final Bson filter, - final T replacement, + final TDocument replacement, final ClientReplaceOptions options) { notNull("namespace", namespace); notNull("filter", filter); notNull("replacement", replacement); notNull("options", options); - return new ClientReplaceOneModel<>(namespace, filter, replacement, options); + return new ClientReplaceOneModel(namespace, filter, replacement, options); } /** @@ -297,15 +287,14 @@ static ClientWriteModel replaceOne( * @param namespace The namespace. * @param filter The filter. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel deleteOne( + static ClientWriteModel deleteOne( final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); - return new ClientDeleteOneModel<>(namespace, filter, null); + return new ClientDeleteOneModel(namespace, filter, null); } /** @@ -315,17 +304,16 @@ static ClientWriteModel deleteOne( * @param filter The filter. * @param options The options. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel deleteOne( + static ClientWriteModel deleteOne( final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); - return new ClientDeleteOneModel<>(namespace, filter, options); + return new ClientDeleteOneModel(namespace, filter, options); } /** @@ -336,15 +324,14 @@ static ClientWriteModel deleteOne( * @param namespace The namespace. * @param filter The filter. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel deleteMany( + static ClientWriteModel deleteMany( final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); - return new ClientDeleteManyModel<>(namespace, filter, null); + return new ClientDeleteManyModel(namespace, filter, null); } /** @@ -354,16 +341,15 @@ static ClientWriteModel deleteMany( * @param filter The filter. * @param options The options. * @return The requested model. - * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel deleteMany( + static ClientWriteModel deleteMany( final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); - return new ClientDeleteManyModel<>(namespace, filter, options); + return new ClientDeleteManyModel(namespace, filter, options); } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java index d506045981d..2f0d28afdd3 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java @@ -24,7 +24,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientDeleteManyModel implements ClientWriteModel { +public final class ClientDeleteManyModel implements ClientWriteModel { private final MongoNamespace namespace; private final Bson filter; private final ConcreteClientDeleteOptions options; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java index 45a21d7d75a..01cd00acdd4 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java @@ -24,7 +24,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientDeleteOneModel implements ClientWriteModel { +public final class ClientDeleteOneModel implements ClientWriteModel { private final MongoNamespace namespace; private final Bson filter; private final ConcreteClientDeleteOptions options; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java index c7648a33325..6fed15a64a2 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java @@ -21,13 +21,13 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientInsertOneModel implements ClientWriteModel { +public final class ClientInsertOneModel implements ClientWriteModel { private final MongoNamespace namespace; - private final T document; + private final Object document; public ClientInsertOneModel( final MongoNamespace namespace, - final T document) { + final Object document) { this.namespace = namespace; this.document = document; } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java index 8749c8cf161..c9c606ab47f 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java @@ -24,16 +24,16 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientReplaceOneModel implements ClientWriteModel { +public final class ClientReplaceOneModel implements ClientWriteModel { private final MongoNamespace namespace; private final Bson filter; - private final T replacement; + private final Object replacement; private final ConcreteClientReplaceOptions options; public ClientReplaceOneModel( final MongoNamespace namespace, final Bson filter, - final T replacement, + final Object replacement, @Nullable final ClientReplaceOptions options) { this.namespace = namespace; this.filter = filter; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java index e723d7f6789..26d906c38c8 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java @@ -26,7 +26,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientUpdateManyModel implements ClientWriteModel { +public final class ClientUpdateManyModel implements ClientWriteModel { private final MongoNamespace namespace; private final Bson filter; @Nullable diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java index ea573e7d136..15245c59e34 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java @@ -26,7 +26,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientUpdateOneModel implements ClientWriteModel { +public final class ClientUpdateOneModel implements ClientWriteModel { private final MongoNamespace namespace; private final Bson filter; @Nullable diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt index c7a1fd65fc5..cd05526a4f3 100644 --- a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt @@ -114,34 +114,28 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) - override fun bulkWrite( - models: MutableList>, - documentClass: Class - ): ClientBulkWriteResult { + override fun bulkWrite(models: MutableList): ClientBulkWriteResult { TODO("BULK-TODO implement") } - override fun bulkWrite( - models: MutableList>, - options: ClientBulkWriteOptions, - documentClass: Class + override fun bulkWrite( + models: MutableList, + options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") } - override fun bulkWrite( + override fun bulkWrite( clientSession: ClientSession, - models: MutableList>, - documentClass: Class + models: MutableList ): ClientBulkWriteResult { TODO("BULK-TODO implement") } - override fun bulkWrite( + override fun bulkWrite( clientSession: ClientSession, - models: MutableList>, - options: ClientBulkWriteOptions, - documentClass: Class + models: MutableList, + options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") } diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt index 2c7f87cceeb..6ed8caf2f94 100644 --- a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt @@ -113,34 +113,28 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) - override fun bulkWrite( - models: MutableList>, - documentClass: Class - ): ClientBulkWriteResult { + override fun bulkWrite(models: MutableList): ClientBulkWriteResult { TODO("BULK-TODO implement") } - override fun bulkWrite( - models: MutableList>, - options: ClientBulkWriteOptions, - documentClass: Class + override fun bulkWrite( + models: MutableList, + options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") } - override fun bulkWrite( + override fun bulkWrite( clientSession: ClientSession, - models: MutableList>, - documentClass: Class + models: MutableList ): ClientBulkWriteResult { TODO("BULK-TODO implement") } - override fun bulkWrite( + override fun bulkWrite( clientSession: ClientSession, - models: MutableList>, - options: ClientBulkWriteOptions, - documentClass: Class + models: MutableList, + options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java index b8f7f37c42c..346f8754085 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java @@ -279,35 +279,31 @@ public void close() { @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientWriteModels, tDocumentClass); + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels); } @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientWriteModels, options, tDocumentClass); + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels, options); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientSession, clientWriteModels, tDocumentClass); + final List clientWriteModels) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientSession, clientWriteModels, options, tDocumentClass); + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels, options); } @Override diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java index 7d83b825ee2..f8c15dc4175 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java @@ -284,34 +284,30 @@ public ChangeStreamIterable watch(final ClientSession clientS } @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala index 15f6b5ad387..388f20ed3d3 100644 --- a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala +++ b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala @@ -128,31 +128,27 @@ class SyncMongoCluster(wrapped: MongoCluster) extends JMongoCluster { private def unwrap(clientSession: ClientSession): org.mongodb.scala.ClientSession = clientSession.asInstanceOf[SyncClientSession].wrapped - override def bulkWrite[TDocument]( - models: util.List[_ <: ClientWriteModel[_ <: TDocument]], - documentClass: Class[TDocument] + override def bulkWrite( + models: util.List[_ <: ClientWriteModel] ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") - override def bulkWrite[TDocument]( - models: util.List[_ <: ClientWriteModel[_ <: TDocument]], - options: ClientBulkWriteOptions, - documentClass: Class[TDocument] + override def bulkWrite( + models: util.List[_ <: ClientWriteModel], + options: ClientBulkWriteOptions ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") - override def bulkWrite[TDocument]( + override def bulkWrite( clientSession: ClientSession, - models: util.List[_ <: ClientWriteModel[_ <: TDocument]], - documentClass: Class[TDocument] + models: util.List[_ <: ClientWriteModel] ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") - override def bulkWrite[TDocument]( + override def bulkWrite( clientSession: ClientSession, - models: util.List[_ <: ClientWriteModel[_ <: TDocument]], - options: ClientBulkWriteOptions, - documentClass: Class[TDocument] + models: util.List[_ <: ClientWriteModel], + options: ClientBulkWriteOptions ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") } diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index baffe62009d..ade33bf28d3 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -360,13 +360,11 @@ public interface MongoCluster { /** * Executes a client-level bulk write operation. - * This method is functionally equivalent to {@link #bulkWrite(List, ClientBulkWriteOptions, Class)} + * This method is functionally equivalent to {@link #bulkWrite(List, ClientBulkWriteOptions)} * with the {@linkplain ClientBulkWriteOptions#clientBulkWriteOptions() default options}. * * @param models The {@linkplain ClientWriteModel individual write operations}. - * @param documentClass The document class. * @return The {@link ClientBulkWriteResult} if the operation is successful. - * @param The document type, for example {@link Document}. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, @@ -376,18 +374,14 @@ public interface MongoCluster { * @mongodb.server.release 8.0 * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ - ClientBulkWriteResult bulkWrite( - List> models, - Class documentClass) throws ClientBulkWriteException; + ClientBulkWriteResult bulkWrite(List models) throws ClientBulkWriteException; /** * Executes a client-level bulk write operation. * * @param models The {@linkplain ClientWriteModel individual write operations}. * @param options The options. - * @param documentClass The document class. * @return The {@link ClientBulkWriteResult} if the operation is successful. - * @param The document type, for example {@link Document}. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, @@ -397,21 +391,18 @@ ClientBulkWriteResult bulkWrite( * @mongodb.server.release 8.0 * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ - ClientBulkWriteResult bulkWrite( - List> models, - ClientBulkWriteOptions options, - Class documentClass) throws ClientBulkWriteException; + ClientBulkWriteResult bulkWrite( + List models, + ClientBulkWriteOptions options) throws ClientBulkWriteException; /** * Executes a client-level bulk write operation. - * This method is functionally equivalent to {@link #bulkWrite(ClientSession, List, ClientBulkWriteOptions, Class)} + * This method is functionally equivalent to {@link #bulkWrite(ClientSession, List, ClientBulkWriteOptions)} * with the {@linkplain ClientBulkWriteOptions#clientBulkWriteOptions() default options}. * * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. * @param models The {@linkplain ClientWriteModel individual write operations}. - * @param documentClass The document class. * @return The {@link ClientBulkWriteResult} if the operation is successful. - * @param The document type, for example {@link Document}. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, @@ -421,10 +412,9 @@ ClientBulkWriteResult bulkWrite( * @mongodb.server.release 8.0 * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ - ClientBulkWriteResult bulkWrite( + ClientBulkWriteResult bulkWrite( ClientSession clientSession, - List> models, - Class documentClass) throws ClientBulkWriteException; + List models) throws ClientBulkWriteException; /** * Executes a client-level bulk write operation. @@ -432,9 +422,7 @@ ClientBulkWriteResult bulkWrite( * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. * @param models The {@linkplain ClientWriteModel individual write operations}. * @param options The options. - * @param documentClass The document class. * @return The {@link ClientBulkWriteResult} if the operation is successful. - * @param The document type, for example {@link Document}. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: * {@link ClientBulkWriteException#getWriteConcernErrors()}, {@link ClientBulkWriteException#getWriteErrors()}, @@ -444,9 +432,8 @@ ClientBulkWriteResult bulkWrite( * @mongodb.server.release 8.0 * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ - ClientBulkWriteResult bulkWrite( + ClientBulkWriteResult bulkWrite( ClientSession clientSession, - List> models, - ClientBulkWriteOptions options, - Class documentClass) throws ClientBulkWriteException; + List models, + ClientBulkWriteOptions options) throws ClientBulkWriteException; } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java index 4ece29fd18a..792e604f182 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java @@ -261,35 +261,31 @@ public ChangeStreamIterable watch( } @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientWriteModels, tDocumentClass); + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels); } @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientWriteModels, options, tDocumentClass); + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { + return delegate.bulkWrite(clientWriteModels, options); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientSession, clientWriteModels, tDocumentClass); + final List clientWriteModels) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { - return delegate.bulkWrite(clientSession, clientWriteModels, options, tDocumentClass); + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { + return delegate.bulkWrite(clientSession, clientWriteModels, options); } private static Cluster createCluster(final MongoClientSettings settings, diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index 18cd27174f2..1b60d95e2fc 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -313,46 +313,38 @@ public ChangeStreamIterable watch(final ClientSession clientS } @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); - notNull("tDocumentClass", tDocumentClass); throw Assertions.fail("BULK-TODO implement"); } @Override - public ClientBulkWriteResult bulkWrite( - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { + public ClientBulkWriteResult bulkWrite( + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); notNull("options", options); - notNull("tDocumentClass", tDocumentClass); throw Assertions.fail("BULK-TODO implement"); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final Class tDocumentClass) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); - notNull("tDocumentClass", tDocumentClass); throw Assertions.fail("BULK-TODO implement"); } @Override - public ClientBulkWriteResult bulkWrite( + public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List> clientWriteModels, - final ClientBulkWriteOptions options, - final Class tDocumentClass) throws ClientBulkWriteException { + final List clientWriteModels, + final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); notNull("options", options); - notNull("tDocumentClass", tDocumentClass); throw Assertions.fail("BULK-TODO implement"); } From 1eb7466e4fc36edce393c7c4162b98cc89620afa Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 25 Jul 2024 17:08:26 -0600 Subject: [PATCH 03/59] Remove `ClientBulkWriteException.create` as we can get by with the constructor JAVA-5527 --- .../com/mongodb/ClientBulkWriteException.java | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index 66c428a4222..1ed748989d7 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -48,50 +48,45 @@ public final class ClientBulkWriteException extends MongoServerException { @Nullable private final ClientBulkWriteResult partialResult; - private ClientBulkWriteException( - final String message, + /** + * Constructs a new instance. + * + * @param error The {@linkplain #getError() top-level error}. + * @param writeConcernErrors The {@linkplain #getWriteConcernErrors() write concern errors}. + * @param writeErrors The {@linkplain #getWriteErrors() write errors}. + * @param partialResult The {@linkplain #getPartialResult() partial result}. + * @param serverAddress The {@linkplain MongoServerException#getServerAddress() server address}. + */ + public ClientBulkWriteException( @Nullable final MongoException error, @Nullable final List writeConcernErrors, @Nullable final Map writeErrors, @Nullable final ClientBulkWriteResult partialResult, final ServerAddress serverAddress) { - super(message, serverAddress); + super(message(error, writeConcernErrors, writeErrors, partialResult, serverAddress), serverAddress); // BULK-TODO Should ClientBulkWriteException.getCode be the same as error.getCode, // and getErrorLabels/hasErrorLabel contain the same labels as error.getErrorLabels? + isTrueArgument("At least one of `writeConcernErrors`, `writeErrors`, `partialResult` must be non-null or non-empty", + !(writeConcernErrors == null || writeConcernErrors.isEmpty()) + || !(writeErrors == null || writeErrors.isEmpty()) + || partialResult != null); this.error = error; this.writeConcernErrors = writeConcernErrors == null ? emptyList() : unmodifiableList(writeConcernErrors); this.writeErrors = writeErrors == null ? emptyMap() : unmodifiableMap(writeErrors); this.partialResult = partialResult; } - /** - * Creates a {@link ClientBulkWriteException}. - * At least one of {@code error}, {@code writeConcernErrors}, {@code writeErrors}, {@code partialResult} - * must be non-{@code null} or non-empty. - * - * @param error The {@linkplain #getError() top-level error}. - * @param writeConcernErrors The {@linkplain #getWriteConcernErrors() write concern errors}. - * @param writeErrors The {@linkplain #getWriteErrors() write errors}. - * @param partialResult The {@linkplain #getPartialResult() partial result}. - * @param serverAddress The {@linkplain MongoServerException#getServerAddress() server address}. - * @return The requested {@link ClientBulkWriteException}. - */ - public static ClientBulkWriteException create( + private static String message( @Nullable final MongoException error, @Nullable final List writeConcernErrors, @Nullable final Map writeErrors, @Nullable final ClientBulkWriteResult partialResult, final ServerAddress serverAddress) { - isTrueArgument("At least one of `writeConcernErrors`, `writeErrors`, `partialResult` must be non-null or non-empty", - !(writeConcernErrors == null || writeConcernErrors.isEmpty()) - || !(writeErrors == null || writeErrors.isEmpty()) - || partialResult != null); - String message = "Client-level bulk write operation error on server " + serverAddress + "." + return "Client-level bulk write operation error on server " + serverAddress + "." + (error == null ? "" : " Top-level error: " + error + ".") + (writeErrors == null || writeErrors.isEmpty() ? "" : " Write errors: " + writeErrors + ".") + (writeConcernErrors == null || writeConcernErrors.isEmpty() ? "" : " Write concern errors: " + writeConcernErrors + ".") + (partialResult == null ? "" : " Partial result: " + partialResult + "."); - return new ClientBulkWriteException(message, error, writeConcernErrors, writeErrors, partialResult, serverAddress); } /** From f566303402d04c207e793ca809a0d0edded98cac Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 14 Aug 2024 18:48:06 -0600 Subject: [PATCH 04/59] Do minor improvements JAVA-5527 --- .../internal/client/model/bulk/ClientDeleteManyModel.java | 2 +- .../internal/client/model/bulk/ClientDeleteOneModel.java | 2 +- .../internal/client/model/bulk/ClientReplaceOneModel.java | 2 +- .../internal/client/model/bulk/ClientUpdateManyModel.java | 2 +- .../internal/client/model/bulk/ClientUpdateOneModel.java | 2 +- .../internal/client/model/bulk/ConcreteClientDeleteOptions.java | 2 +- .../client/model/bulk/ConcreteClientReplaceOptions.java | 2 +- .../internal/client/model/bulk/ConcreteClientUpdateOptions.java | 2 +- .../client/result/bulk/UnacknowledgedClientBulkWriteResult.java | 2 ++ 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java index 2f0d28afdd3..ee2df37e8c0 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java @@ -35,7 +35,7 @@ public ClientDeleteManyModel( @Nullable final ClientDeleteOptions options) { this.namespace = namespace; this.filter = filter; - this.options = options == null ? ConcreteClientDeleteOptions.EMPTY : (ConcreteClientDeleteOptions) options; + this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; } @Override diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java index 01cd00acdd4..c108c2606c0 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java @@ -35,7 +35,7 @@ public ClientDeleteOneModel( @Nullable final ClientDeleteOptions options) { this.namespace = namespace; this.filter = filter; - this.options = options == null ? ConcreteClientDeleteOptions.EMPTY : (ConcreteClientDeleteOptions) options; + this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; } @Override diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java index c9c606ab47f..24274072c24 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java @@ -38,7 +38,7 @@ public ClientReplaceOneModel( this.namespace = namespace; this.filter = filter; this.replacement = replacement; - this.options = options == null ? ConcreteClientReplaceOptions.EMPTY : (ConcreteClientReplaceOptions) options; + this.options = options == null ? ConcreteClientReplaceOptions.MUTABLE_EMPTY : (ConcreteClientReplaceOptions) options; } @Override diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java index 26d906c38c8..a3f7ba43282 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java @@ -48,7 +48,7 @@ public ClientUpdateManyModel( assertTrue(update == null ^ updatePipeline == null); this.update = update; this.updatePipeline = updatePipeline; - this.options = options == null ? ConcreteClientUpdateOptions.EMPTY : (ConcreteClientUpdateOptions) options; + this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; } @Override diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java index 15245c59e34..cbc3c67bd4d 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java @@ -48,7 +48,7 @@ public ClientUpdateOneModel( assertTrue(update == null ^ updatePipeline == null); this.update = update; this.updatePipeline = updatePipeline; - this.options = options == null ? ConcreteClientUpdateOptions.EMPTY : (ConcreteClientUpdateOptions) options; + this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; } @Override diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java index 18215ad4592..0730a198ded 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java @@ -24,7 +24,7 @@ * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientDeleteOptions implements ClientDeleteOptions { - static final ConcreteClientDeleteOptions EMPTY = new ConcreteClientDeleteOptions(); + static final ConcreteClientDeleteOptions MUTABLE_EMPTY = new ConcreteClientDeleteOptions(); @Nullable private Collation collation; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java index 963fee20614..f3d83c81f4c 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java @@ -24,7 +24,7 @@ * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientReplaceOptions implements ClientReplaceOptions { - static final ConcreteClientReplaceOptions EMPTY = new ConcreteClientReplaceOptions(); + static final ConcreteClientReplaceOptions MUTABLE_EMPTY = new ConcreteClientReplaceOptions(); @Nullable private Collation collation; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java index 3d7c13cdd3b..0c6af8059db 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java @@ -24,7 +24,7 @@ * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientUpdateOptions implements ClientUpdateOptions { - static final ConcreteClientUpdateOptions EMPTY = new ConcreteClientUpdateOptions(); + static final ConcreteClientUpdateOptions MUTABLE_EMPTY = new ConcreteClientUpdateOptions(); @Nullable private Iterable arrayFilters; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java index dd508169dee..cf0525aa543 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java @@ -15,6 +15,7 @@ */ package com.mongodb.internal.client.result.bulk; +import com.mongodb.annotations.Immutable; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.client.result.bulk.ClientDeleteResult; import com.mongodb.client.result.bulk.ClientInsertOneResult; @@ -25,6 +26,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ +@Immutable public final class UnacknowledgedClientBulkWriteResult implements ClientBulkWriteResult { public static final UnacknowledgedClientBulkWriteResult INSTANCE = new UnacknowledgedClientBulkWriteResult(); From 3d13ffd0987a2ad9717d719e57eb94ac46a6b8c9 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 14 Aug 2024 19:32:29 -0600 Subject: [PATCH 05/59] Make changes needed for the implementation JAVA-5527 --- .../result/bulk/ClientBulkWriteResult.java | 1 - .../model/bulk/ClientDeleteManyModel.java | 17 +++----- .../model/bulk/ClientDeleteOneModel.java | 14 ++++++- .../model/bulk/ClientInsertOneModel.java | 8 ++++ .../model/bulk/ClientReplaceOneModel.java | 16 ++++++++ .../model/bulk/ClientUpdateManyModel.java | 31 +++++--------- .../model/bulk/ClientUpdateOneModel.java | 25 +++++++++++- .../bulk/ConcreteClientBulkWriteOptions.java | 40 ++++++++++++++++++- .../bulk/ConcreteClientDeleteOptions.java | 25 ++++++++++++ .../bulk/ConcreteClientReplaceOptions.java | 32 +++++++++++++++ .../bulk/ConcreteClientUpdateOptions.java | 39 ++++++++++++++++++ 11 files changed, 210 insertions(+), 38 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java index 4388f793bb9..2cb4706109b 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java @@ -52,7 +52,6 @@ public interface ClientBulkWriteResult { * @return Whether there are verbose results. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - // BULK-TODO Do we still have getInsertedCount etc., when there are no verbose results? boolean hasVerboseResults() throws UnsupportedOperationException; /** diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java index ee2df37e8c0..fd4252987cb 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java @@ -17,33 +17,26 @@ import com.mongodb.MongoNamespace; import com.mongodb.client.model.bulk.ClientDeleteOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientDeleteManyModel implements ClientWriteModel { - private final MongoNamespace namespace; - private final Bson filter; - private final ConcreteClientDeleteOptions options; - +public final class ClientDeleteManyModel extends ClientDeleteOneModel { public ClientDeleteManyModel( final MongoNamespace namespace, final Bson filter, @Nullable final ClientDeleteOptions options) { - this.namespace = namespace; - this.filter = filter; - this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; + super(namespace, filter, options); } @Override public String toString() { return "ClientDeleteManyModel{" - + "namespace=" + namespace - + ", filter=" + filter - + ", options=" + options + + "namespace=" + getNamespace() + + ", filter=" + getFilter() + + ", options=" + getOptions() + '}'; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java index c108c2606c0..5c7fe865186 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java @@ -24,7 +24,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientDeleteOneModel implements ClientWriteModel { +public class ClientDeleteOneModel implements ClientWriteModel { private final MongoNamespace namespace; private final Bson filter; private final ConcreteClientDeleteOptions options; @@ -38,6 +38,18 @@ public ClientDeleteOneModel( this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; } + public MongoNamespace getNamespace() { + return namespace; + } + + public Bson getFilter() { + return filter; + } + + public ConcreteClientDeleteOptions getOptions() { + return options; + } + @Override public String toString() { return "ClientDeleteOneModel{" diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java index 6fed15a64a2..04cd7a67ccc 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java @@ -32,6 +32,14 @@ public ClientInsertOneModel( this.document = document; } + public MongoNamespace getNamespace() { + return namespace; + } + + public Object getDocument() { + return document; + } + @Override public String toString() { return "ClientInsertOneModel{" diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java index 24274072c24..6ea074efa2d 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java @@ -41,6 +41,22 @@ public ClientReplaceOneModel( this.options = options == null ? ConcreteClientReplaceOptions.MUTABLE_EMPTY : (ConcreteClientReplaceOptions) options; } + public MongoNamespace getNamespace() { + return namespace; + } + + public Bson getFilter() { + return filter; + } + + public Object getReplacement() { + return replacement; + } + + public ConcreteClientReplaceOptions getOptions() { + return options; + } + @Override public String toString() { return "ClientReplaceOneModel{" diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java index a3f7ba43282..f2f36364db9 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java @@ -16,25 +16,15 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; +import com.mongodb.assertions.Assertions; import com.mongodb.client.model.bulk.ClientUpdateOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; -import static com.mongodb.assertions.Assertions.assertTrue; - /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientUpdateManyModel implements ClientWriteModel { - private final MongoNamespace namespace; - private final Bson filter; - @Nullable - private final Bson update; - @Nullable - private final Iterable updatePipeline; - private final ConcreteClientUpdateOptions options; - +public final class ClientUpdateManyModel extends ClientUpdateOneModel { public ClientUpdateManyModel( final MongoNamespace namespace, final Bson filter, @@ -43,21 +33,18 @@ public ClientUpdateManyModel( @Nullable final Iterable updatePipeline, @Nullable final ClientUpdateOptions options) { - this.namespace = namespace; - this.filter = filter; - assertTrue(update == null ^ updatePipeline == null); - this.update = update; - this.updatePipeline = updatePipeline; - this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; + super(namespace, filter, update, updatePipeline, options); } @Override public String toString() { return "ClientUpdateManyModel{" - + "namespace=" + namespace - + ", filter=" + filter - + ", update=" + (update != null ? update : updatePipeline) - + ", options=" + options + + "namespace=" + getNamespace() + + ", filter=" + getFilter() + + ", update=" + getUpdate().map(Object::toString) + .orElse(getUpdatePipeline().map(Object::toString) + .orElseThrow(Assertions::fail)) + + ", options=" + getOptions() + '}'; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java index cbc3c67bd4d..e8faf5378b2 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java @@ -21,12 +21,15 @@ import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; +import java.util.Optional; + import static com.mongodb.assertions.Assertions.assertTrue; +import static java.util.Optional.ofNullable; /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientUpdateOneModel implements ClientWriteModel { +public class ClientUpdateOneModel implements ClientWriteModel { private final MongoNamespace namespace; private final Bson filter; @Nullable @@ -51,6 +54,26 @@ public ClientUpdateOneModel( this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; } + public MongoNamespace getNamespace() { + return namespace; + } + + public Bson getFilter() { + return filter; + } + + public Optional getUpdate() { + return ofNullable(update); + } + + public Optional> getUpdatePipeline() { + return ofNullable(updatePipeline); + } + + public ConcreteClientUpdateOptions getOptions() { + return options; + } + @Override public String toString() { return "ClientUpdateOneModel{" diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java index 95492698522..9599e1750bf 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientBulkWriteOptions.java @@ -20,11 +20,14 @@ import org.bson.BsonValue; import org.bson.conversions.Bson; +import java.util.Optional; + +import static java.util.Optional.ofNullable; + /** * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientBulkWriteOptions implements ClientBulkWriteOptions { - // BULK-TODO Introduce EMPTY similar to ConcreteClientUpdateOptions.EMPTY. private static final Boolean CLIENT_DEFAULT_ORDERED = true; private static final Boolean CLIENT_DEFAULT_VERBOSE_RESULTS = false; @@ -48,30 +51,65 @@ public ClientBulkWriteOptions ordered(@Nullable final Boolean ordered) { return this; } + /** + * @see #ordered(Boolean) + */ + public boolean isOrdered() { + return ordered == null ? CLIENT_DEFAULT_ORDERED : ordered; + } + @Override public ClientBulkWriteOptions bypassDocumentValidation(@Nullable final Boolean bypassDocumentValidation) { this.bypassDocumentValidation = bypassDocumentValidation; return this; } + /** + * @see #bypassDocumentValidation(Boolean) + */ + public Optional isBypassDocumentValidation() { + return ofNullable(bypassDocumentValidation); + } + @Override public ClientBulkWriteOptions let(@Nullable final Bson let) { this.let = let; return this; } + /** + * @see #let(Bson) + */ + public Optional getLet() { + return ofNullable(let); + } + @Override public ClientBulkWriteOptions comment(@Nullable final BsonValue comment) { this.comment = comment; return this; } + /** + * @see #comment(BsonValue) + */ + public Optional getComment() { + return ofNullable(comment); + } + @Override public ClientBulkWriteOptions verboseResults(@Nullable final Boolean verboseResults) { this.verboseResults = verboseResults; return this; } + /** + * @see #verboseResults(Boolean) + */ + public boolean isVerboseResults() { + return verboseResults == null ? CLIENT_DEFAULT_VERBOSE_RESULTS : verboseResults; + } + @Override public String toString() { return "ClientBulkWriteOptions{" diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java index 0730a198ded..1acef43052b 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOptions.java @@ -20,6 +20,10 @@ import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; +import java.util.Optional; + +import static java.util.Optional.ofNullable; + /** * This class is not part of the public API and may be removed or changed at any time. */ @@ -42,6 +46,13 @@ public ClientDeleteOptions collation(@Nullable final Collation collation) { return this; } + /** + * @see #collation(Collation) + */ + public Optional getCollation() { + return ofNullable(collation); + } + @Override public ClientDeleteOptions hint(@Nullable final Bson hint) { this.hint = hint; @@ -49,6 +60,13 @@ public ClientDeleteOptions hint(@Nullable final Bson hint) { return this; } + /** + * @see #hint(Bson) + */ + public Optional getHint() { + return ofNullable(hint); + } + @Override public ClientDeleteOptions hintString(@Nullable final String hintString) { this.hintString = hintString; @@ -56,6 +74,13 @@ public ClientDeleteOptions hintString(@Nullable final String hintString) { return this; } + /** + * @see #hintString(String) + */ + public Optional getHintString() { + return ofNullable(hintString); + } + @Override public String toString() { return "ClientDeleteOptions{" diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java index f3d83c81f4c..703e6b48df0 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOptions.java @@ -20,6 +20,10 @@ import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; +import java.util.Optional; + +import static java.util.Optional.ofNullable; + /** * This class is not part of the public API and may be removed or changed at any time. */ @@ -44,6 +48,13 @@ public ClientReplaceOptions collation(@Nullable final Collation collation) { return this; } + /** + * @see #collation(Collation) + */ + public Optional getCollation() { + return ofNullable(collation); + } + @Override public ClientReplaceOptions hint(@Nullable final Bson hint) { this.hint = hint; @@ -51,6 +62,13 @@ public ClientReplaceOptions hint(@Nullable final Bson hint) { return this; } + /** + * @see #hint(Bson) + */ + public Optional getHint() { + return ofNullable(hint); + } + @Override public ClientReplaceOptions hintString(@Nullable final String hintString) { this.hintString = hintString; @@ -58,12 +76,26 @@ public ClientReplaceOptions hintString(@Nullable final String hintString) { return this; } + /** + * @see #hintString(String) + */ + public Optional getHintString() { + return ofNullable(hintString); + } + @Override public ClientReplaceOptions upsert(@Nullable final Boolean upsert) { this.upsert = upsert; return this; } + /** + * @see #upsert(Boolean) + */ + public Optional isUpsert() { + return ofNullable(upsert); + } + @Override public String toString() { return "ClientReplaceOptions{" diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java index 0c6af8059db..cdb0d08839b 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOptions.java @@ -20,6 +20,10 @@ import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; +import java.util.Optional; + +import static java.util.Optional.ofNullable; + /** * This class is not part of the public API and may be removed or changed at any time. */ @@ -46,12 +50,26 @@ public ClientUpdateOptions arrayFilters(@Nullable final Iterable return this; } + /** + * @see #arrayFilters(Iterable) + */ + public Optional> getArrayFilters() { + return ofNullable(arrayFilters); + } + @Override public ClientUpdateOptions collation(@Nullable final Collation collation) { this.collation = collation; return this; } + /** + * @see #collation(Collation) + */ + public Optional getCollation() { + return ofNullable(collation); + } + @Override public ClientUpdateOptions hint(@Nullable final Bson hint) { this.hint = hint; @@ -59,6 +77,13 @@ public ClientUpdateOptions hint(@Nullable final Bson hint) { return this; } + /** + * @see #hint(Bson) + */ + public Optional getHint() { + return ofNullable(hint); + } + @Override public ClientUpdateOptions hintString(@Nullable final String hintString) { this.hintString = hintString; @@ -66,12 +91,26 @@ public ClientUpdateOptions hintString(@Nullable final String hintString) { return this; } + /** + * @see #hintString(String) + */ + public Optional getHintString() { + return ofNullable(hintString); + } + @Override public ClientUpdateOptions upsert(@Nullable final Boolean upsert) { this.upsert = upsert; return this; } + /** + * @see #isUpsert() + */ + public Optional isUpsert() { + return ofNullable(upsert); + } + @Override public String toString() { return "ClientUpdateOptions{" From cf46b4617d92aa73c5ab4e68c3517093896dddba Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 14 Aug 2024 19:40:41 -0600 Subject: [PATCH 06/59] Fix formatting in ClientUpdateManyModel JAVA-5527 --- .../internal/client/model/bulk/ClientUpdateManyModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java index f2f36364db9..b3ba01cf07f 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java @@ -42,7 +42,7 @@ public String toString() { + "namespace=" + getNamespace() + ", filter=" + getFilter() + ", update=" + getUpdate().map(Object::toString) - .orElse(getUpdatePipeline().map(Object::toString) + .orElse(getUpdatePipeline().map(Object::toString) .orElseThrow(Assertions::fail)) + ", options=" + getOptions() + '}'; From e04923486521d760374b36da4f8d6bc27096a480 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 15 Aug 2024 02:56:36 -0600 Subject: [PATCH 07/59] Make a few minor changes JAVA-5527 --- .../client/result/bulk/ClientBulkWriteResult.java | 2 -- .../AcknowledgedVerboseClientBulkWriteResult.java | 14 ++++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java index 2cb4706109b..b30aaec4365 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java @@ -86,8 +86,6 @@ public interface ClientBulkWriteResult { */ long getModifiedCount() throws UnsupportedOperationException; - // BULK-TODO Is ReplaceOne reported as 1 modified (I expect this behavior), or 1 deleted and 1 inserted? - /** * The number of documents that were deleted across all delete operations. * diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java index 75e8650e5b3..a84cb3dee54 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -19,12 +19,10 @@ import com.mongodb.client.result.bulk.ClientDeleteResult; import com.mongodb.client.result.bulk.ClientInsertOneResult; import com.mongodb.client.result.bulk.ClientUpdateResult; -import com.mongodb.lang.Nullable; import java.util.Map; import java.util.Objects; -import static java.util.Collections.emptyMap; import static java.util.Collections.unmodifiableMap; /** @@ -38,13 +36,13 @@ public final class AcknowledgedVerboseClientBulkWriteResult implements ClientBul public AcknowledgedVerboseClientBulkWriteResult( final AcknowledgedSummaryClientBulkWriteResult summaryResults, - @Nullable final Map insertResults, - @Nullable final Map updateResults, - @Nullable final Map deleteResults) { + final Map insertResults, + final Map updateResults, + final Map deleteResults) { this.summaryResults = summaryResults; - this.insertResults = insertResults == null ? emptyMap() : unmodifiableMap(insertResults); - this.updateResults = updateResults == null ? emptyMap() : unmodifiableMap(updateResults); - this.deleteResults = deleteResults == null ? emptyMap() : unmodifiableMap(deleteResults); + this.insertResults = unmodifiableMap(insertResults); + this.updateResults = unmodifiableMap(updateResults); + this.deleteResults = unmodifiableMap(deleteResults); } @Override From 0d518d8cf792d0bb2b755ab1ba3d57acb5b7197d Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 01:34:30 -0600 Subject: [PATCH 08/59] Add more info to the API docs, add `ClientWriteModel` subtypes JAVA-5527 --- .../model/bulk/ClientDeleteManyModel.java | 28 +++++++ .../model/bulk/ClientDeleteOneModel.java | 28 +++++++ .../model/bulk/ClientInsertOneModel.java | 28 +++++++ .../model/bulk/ClientReplaceOneModel.java | 28 +++++++ .../model/bulk/ClientUpdateManyModel.java | 28 +++++++ .../model/bulk/ClientUpdateOneModel.java | 28 +++++++ .../client/model/bulk/ClientWriteModel.java | 83 ++++++++++--------- ...ava => ConcreteClientDeleteManyModel.java} | 5 +- ...java => ConcreteClientDeleteOneModel.java} | 6 +- ...java => ConcreteClientInsertOneModel.java} | 6 +- ...ava => ConcreteClientReplaceOneModel.java} | 6 +- ...ava => ConcreteClientUpdateManyModel.java} | 5 +- ...java => ConcreteClientUpdateOneModel.java} | 6 +- .../main/com/mongodb/client/MongoCluster.java | 27 ++++++ 14 files changed, 256 insertions(+), 56 deletions(-) create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneModel.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOneModel.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateManyModel.java create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOneModel.java rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ClientDeleteManyModel.java => ConcreteClientDeleteManyModel.java} (85%) rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ClientDeleteOneModel.java => ConcreteClientDeleteOneModel.java} (91%) rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ClientInsertOneModel.java => ConcreteClientInsertOneModel.java} (88%) rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ClientReplaceOneModel.java => ConcreteClientReplaceOneModel.java} (91%) rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ClientUpdateManyModel.java => ConcreteClientUpdateManyModel.java} (88%) rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ClientUpdateOneModel.java => ConcreteClientUpdateOneModel.java} (93%) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java new file mode 100644 index 00000000000..a5770169445 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; + +/** + * A model for removing all documents matching a filter. + * + * @since 5.3 + */ +@Sealed +public interface ClientDeleteManyModel extends ClientWriteModel { +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java new file mode 100644 index 00000000000..77ad1999680 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; + +/** + * A model for removing at most one document matching a filter. + * + * @since 5.3 + */ +@Sealed +public interface ClientDeleteOneModel extends ClientWriteModel { +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneModel.java new file mode 100644 index 00000000000..7237490a133 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; + +/** + * A model for inserting a document. + * + * @since 5.3 + */ +@Sealed +public interface ClientInsertOneModel extends ClientWriteModel { +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOneModel.java new file mode 100644 index 00000000000..c3467266cc1 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; + +/** + * A model for replacing at most one document matching a filter. + * + * @since 5.3 + */ +@Sealed +public interface ClientReplaceOneModel extends ClientWriteModel { +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateManyModel.java new file mode 100644 index 00000000000..459cde6fcd2 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateManyModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; + +/** + * A model for updating all documents matching a filter. + * + * @since 5.3 + */ +@Sealed +public interface ClientUpdateManyModel extends ClientWriteModel { +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOneModel.java new file mode 100644 index 00000000000..ad5255b53eb --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.annotations.Sealed; + +/** + * A model for updating at most one document matching a filter. + * + * @since 5.3 + */ +@Sealed +public interface ClientUpdateOneModel extends ClientWriteModel { +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java index 683fce6f5a4..1357242eef7 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java @@ -17,14 +17,15 @@ import com.mongodb.MongoNamespace; import com.mongodb.annotations.Sealed; +import com.mongodb.client.model.Aggregates; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; -import com.mongodb.internal.client.model.bulk.ClientDeleteManyModel; -import com.mongodb.internal.client.model.bulk.ClientDeleteOneModel; -import com.mongodb.internal.client.model.bulk.ClientInsertOneModel; -import com.mongodb.internal.client.model.bulk.ClientReplaceOneModel; -import com.mongodb.internal.client.model.bulk.ClientUpdateManyModel; -import com.mongodb.internal.client.model.bulk.ClientUpdateOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientInsertOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; import org.bson.Document; import org.bson.conversions.Bson; @@ -46,12 +47,12 @@ public interface ClientWriteModel { * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel insertOne( + static ClientInsertOneModel insertOne( final MongoNamespace namespace, final TDocument document) { notNull("namespace", namespace); notNull("document", document); - return new ClientInsertOneModel(namespace, document); + return new ConcreteClientInsertOneModel(namespace, document); } /** @@ -66,14 +67,14 @@ static ClientWriteModel insertOne( * @see Filters * @see Updates */ - static ClientWriteModel updateOne( + static ClientUpdateOneModel updateOne( final MongoNamespace namespace, final Bson filter, final Bson update) { notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); - return new ClientUpdateOneModel(namespace, filter, update, null, null); + return new ConcreteClientUpdateOneModel(namespace, filter, update, null, null); } /** @@ -87,7 +88,7 @@ static ClientWriteModel updateOne( * @see Filters * @see Updates */ - static ClientWriteModel updateOne( + static ClientUpdateOneModel updateOne( final MongoNamespace namespace, final Bson filter, final Bson update, @@ -96,7 +97,7 @@ static ClientWriteModel updateOne( notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ClientUpdateOneModel(namespace, filter, update, null, options); + return new ConcreteClientUpdateOneModel(namespace, filter, update, null, options); } /** @@ -109,16 +110,16 @@ static ClientWriteModel updateOne( * @param updatePipeline The update pipeline. * @return The requested model. * @see Filters - * @see Updates + * @see Aggregates */ - static ClientWriteModel updateOne( + static ClientUpdateOneModel updateOne( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ClientUpdateOneModel(namespace, filter, null, updatePipeline, null); + return new ConcreteClientUpdateOneModel(namespace, filter, null, updatePipeline, null); } /** @@ -130,9 +131,9 @@ static ClientWriteModel updateOne( * @param options The options. * @return The requested model. * @see Filters - * @see Updates + * @see Aggregates */ - static ClientWriteModel updateOne( + static ClientUpdateOneModel updateOne( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, @@ -141,7 +142,7 @@ static ClientWriteModel updateOne( notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ClientUpdateOneModel(namespace, filter, null, updatePipeline, options); + return new ConcreteClientUpdateOneModel(namespace, filter, null, updatePipeline, options); } /** @@ -156,14 +157,14 @@ static ClientWriteModel updateOne( * @see Filters * @see Updates */ - static ClientWriteModel updateMany( + static ClientUpdateManyModel updateMany( final MongoNamespace namespace, final Bson filter, final Bson update) { notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); - return new ClientUpdateManyModel(namespace, filter, update, null, null); + return new ConcreteClientUpdateManyModel(namespace, filter, update, null, null); } /** @@ -177,7 +178,7 @@ static ClientWriteModel updateMany( * @see Filters * @see Updates */ - static ClientWriteModel updateMany( + static ClientUpdateManyModel updateMany( final MongoNamespace namespace, final Bson filter, final Bson update, @@ -186,7 +187,7 @@ static ClientWriteModel updateMany( notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ClientUpdateManyModel(namespace, filter, update, null, options); + return new ConcreteClientUpdateManyModel(namespace, filter, update, null, options); } /** @@ -199,16 +200,16 @@ static ClientWriteModel updateMany( * @param updatePipeline The update pipeline. * @return The requested model. * @see Filters - * @see Updates + * @see Aggregates */ - static ClientWriteModel updateMany( + static ClientUpdateManyModel updateMany( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ClientUpdateManyModel(namespace, filter, null, updatePipeline, null); + return new ConcreteClientUpdateManyModel(namespace, filter, null, updatePipeline, null); } /** @@ -220,9 +221,9 @@ static ClientWriteModel updateMany( * @param options The options. * @return The requested model. * @see Filters - * @see Updates + * @see Aggregates */ - static ClientWriteModel updateMany( + static ClientUpdateManyModel updateMany( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, @@ -231,7 +232,7 @@ static ClientWriteModel updateMany( notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ClientUpdateManyModel(namespace, filter, null, updatePipeline, options); + return new ConcreteClientUpdateManyModel(namespace, filter, null, updatePipeline, options); } /** @@ -242,18 +243,19 @@ static ClientWriteModel updateMany( * @param namespace The namespace. * @param filter The filter. * @param replacement The replacement. + * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. * @return The requested model. * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel replaceOne( + static ClientReplaceOneModel replaceOne( final MongoNamespace namespace, final Bson filter, final TDocument replacement) { notNull("namespace", namespace); notNull("filter", filter); notNull("replacement", replacement); - return new ClientReplaceOneModel(namespace, filter, replacement, null); + return new ConcreteClientReplaceOneModel(namespace, filter, replacement, null); } /** @@ -262,12 +264,13 @@ static ClientWriteModel replaceOne( * @param namespace The namespace. * @param filter The filter. * @param replacement The replacement. + * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. * @param options The options. * @return The requested model. * @param The document type, for example {@link Document}. * @see Filters */ - static ClientWriteModel replaceOne( + static ClientReplaceOneModel replaceOne( final MongoNamespace namespace, final Bson filter, final TDocument replacement, @@ -276,7 +279,7 @@ static ClientWriteModel replaceOne( notNull("filter", filter); notNull("replacement", replacement); notNull("options", options); - return new ClientReplaceOneModel(namespace, filter, replacement, options); + return new ConcreteClientReplaceOneModel(namespace, filter, replacement, options); } /** @@ -289,12 +292,12 @@ static ClientWriteModel replaceOne( * @return The requested model. * @see Filters */ - static ClientWriteModel deleteOne( + static ClientDeleteOneModel deleteOne( final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); - return new ClientDeleteOneModel(namespace, filter, null); + return new ConcreteClientDeleteOneModel(namespace, filter, null); } /** @@ -306,14 +309,14 @@ static ClientWriteModel deleteOne( * @return The requested model. * @see Filters */ - static ClientWriteModel deleteOne( + static ClientDeleteOneModel deleteOne( final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); - return new ClientDeleteOneModel(namespace, filter, options); + return new ConcreteClientDeleteOneModel(namespace, filter, options); } /** @@ -326,12 +329,12 @@ static ClientWriteModel deleteOne( * @return The requested model. * @see Filters */ - static ClientWriteModel deleteMany( + static ClientDeleteManyModel deleteMany( final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); - return new ClientDeleteManyModel(namespace, filter, null); + return new ConcreteClientDeleteManyModel(namespace, filter, null); } /** @@ -343,13 +346,13 @@ static ClientWriteModel deleteMany( * @return The requested model. * @see Filters */ - static ClientWriteModel deleteMany( + static ClientDeleteManyModel deleteMany( final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); - return new ClientDeleteManyModel(namespace, filter, options); + return new ConcreteClientDeleteManyModel(namespace, filter, options); } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java similarity index 85% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java index fd4252987cb..d1164975356 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java @@ -16,6 +16,7 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientDeleteManyModel; import com.mongodb.client.model.bulk.ClientDeleteOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -23,8 +24,8 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientDeleteManyModel extends ClientDeleteOneModel { - public ClientDeleteManyModel( +public final class ConcreteClientDeleteManyModel extends ConcreteClientDeleteOneModel implements ClientDeleteManyModel { + public ConcreteClientDeleteManyModel( final MongoNamespace namespace, final Bson filter, @Nullable final ClientDeleteOptions options) { diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java similarity index 91% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java index 5c7fe865186..666cd37ac59 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java @@ -16,20 +16,20 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientDeleteOneModel; import com.mongodb.client.model.bulk.ClientDeleteOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ClientDeleteOneModel implements ClientWriteModel { +public class ConcreteClientDeleteOneModel implements ClientDeleteOneModel { private final MongoNamespace namespace; private final Bson filter; private final ConcreteClientDeleteOptions options; - public ClientDeleteOneModel( + public ConcreteClientDeleteOneModel( final MongoNamespace namespace, final Bson filter, @Nullable final ClientDeleteOptions options) { diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java similarity index 88% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java index 04cd7a67ccc..13ff729e3cf 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientInsertOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java @@ -16,16 +16,16 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientInsertOneModel; /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientInsertOneModel implements ClientWriteModel { +public final class ConcreteClientInsertOneModel implements ClientInsertOneModel { private final MongoNamespace namespace; private final Object document; - public ClientInsertOneModel( + public ConcreteClientInsertOneModel( final MongoNamespace namespace, final Object document) { this.namespace = namespace; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java similarity index 91% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java index 6ea074efa2d..d3d6fac55b4 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java @@ -16,21 +16,21 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientReplaceOneModel; import com.mongodb.client.model.bulk.ClientReplaceOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientReplaceOneModel implements ClientWriteModel { +public final class ConcreteClientReplaceOneModel implements ClientReplaceOneModel { private final MongoNamespace namespace; private final Bson filter; private final Object replacement; private final ConcreteClientReplaceOptions options; - public ClientReplaceOneModel( + public ConcreteClientReplaceOneModel( final MongoNamespace namespace, final Bson filter, final Object replacement, diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java similarity index 88% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java index b3ba01cf07f..2bd6dd023da 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java @@ -17,6 +17,7 @@ import com.mongodb.MongoNamespace; import com.mongodb.assertions.Assertions; +import com.mongodb.client.model.bulk.ClientUpdateManyModel; import com.mongodb.client.model.bulk.ClientUpdateOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -24,8 +25,8 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ClientUpdateManyModel extends ClientUpdateOneModel { - public ClientUpdateManyModel( +public final class ConcreteClientUpdateManyModel extends ConcreteClientUpdateOneModel implements ClientUpdateManyModel { + public ConcreteClientUpdateManyModel( final MongoNamespace namespace, final Bson filter, @Nullable diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java similarity index 93% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java index e8faf5378b2..54406f888fb 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java @@ -16,8 +16,8 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientUpdateOneModel; import com.mongodb.client.model.bulk.ClientUpdateOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -29,7 +29,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ClientUpdateOneModel implements ClientWriteModel { +public class ConcreteClientUpdateOneModel implements ClientUpdateOneModel { private final MongoNamespace namespace; private final Bson filter; @Nullable @@ -38,7 +38,7 @@ public class ClientUpdateOneModel implements ClientWriteModel { private final Iterable updatePipeline; private final ConcreteClientUpdateOptions options; - public ClientUpdateOneModel( + public ConcreteClientUpdateOneModel( final MongoNamespace namespace, final Bson filter, @Nullable diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index ade33bf28d3..96ddf95cbea 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -18,6 +18,7 @@ import com.mongodb.ClientBulkWriteException; import com.mongodb.ClientSessionOptions; +import com.mongodb.MongoClientSettings; import com.mongodb.MongoException; import com.mongodb.MongoNamespace; import com.mongodb.ReadConcern; @@ -27,6 +28,8 @@ import com.mongodb.annotations.Immutable; import com.mongodb.annotations.Reason; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientDeleteManyModel; +import com.mongodb.client.model.bulk.ClientUpdateManyModel; import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.lang.Nullable; @@ -362,6 +365,12 @@ public interface MongoCluster { * Executes a client-level bulk write operation. * This method is functionally equivalent to {@link #bulkWrite(List, ClientBulkWriteOptions)} * with the {@linkplain ClientBulkWriteOptions#clientBulkWriteOptions() default options}. + *

+ * This operation supports {@linkplain MongoClientSettings#getRetryWrites() retryable writes}. + * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, + * executing this operation may require multiple {@code bulkWrite} commands. + * The eligibility for retries is determined per each {@code bulkWrite} command: + * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param models The {@linkplain ClientWriteModel individual write operations}. * @return The {@link ClientBulkWriteResult} if the operation is successful. @@ -378,6 +387,12 @@ public interface MongoCluster { /** * Executes a client-level bulk write operation. + *

+ * This operation supports {@linkplain MongoClientSettings#getRetryWrites() retryable writes}. + * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, + * executing this operation may require multiple {@code bulkWrite} commands. + * The eligibility for retries is determined per each {@code bulkWrite} command: + * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param models The {@linkplain ClientWriteModel individual write operations}. * @param options The options. @@ -399,6 +414,12 @@ ClientBulkWriteResult bulkWrite( * Executes a client-level bulk write operation. * This method is functionally equivalent to {@link #bulkWrite(ClientSession, List, ClientBulkWriteOptions)} * with the {@linkplain ClientBulkWriteOptions#clientBulkWriteOptions() default options}. + *

+ * This operation supports {@linkplain MongoClientSettings#getRetryWrites() retryable writes}. + * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, + * executing this operation may require multiple {@code bulkWrite} commands. + * The eligibility for retries is determined per each {@code bulkWrite} command: + * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. * @param models The {@linkplain ClientWriteModel individual write operations}. @@ -418,6 +439,12 @@ ClientBulkWriteResult bulkWrite( /** * Executes a client-level bulk write operation. + *

+ * This operation supports {@linkplain MongoClientSettings#getRetryWrites() retryable writes}. + * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, + * executing this operation may require multiple {@code bulkWrite} commands. + * The eligibility for retries is determined per each {@code bulkWrite} command: + * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. * @param models The {@linkplain ClientWriteModel individual write operations}. From 6b77f7821517b2461ef52e4fefab54d8dee0eab0 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 04:31:31 -0600 Subject: [PATCH 09/59] Add `ClientWriteModelWithNamespace` JAVA-5527 --- .../client/model/bulk/ClientWriteModel.java | 193 ++++++------------ .../bulk/ClientWriteModelWithNamespace.java | 30 +++ .../bulk/ConcreteClientDeleteManyModel.java | 9 +- .../bulk/ConcreteClientDeleteOneModel.java | 13 +- .../bulk/ConcreteClientInsertOneModel.java | 12 +- .../bulk/ConcreteClientReplaceOneModel.java | 14 +- .../bulk/ConcreteClientUpdateManyModel.java | 5 +- .../bulk/ConcreteClientUpdateOneModel.java | 9 - ...ConcreteClientWriteModelWithNamespace.java | 47 +++++ .../coroutine/syncadapter/SyncMongoCluster.kt | 10 +- .../client/syncadapter/SyncMongoCluster.kt | 10 +- .../client/syncadapter/SyncMongoClient.java | 10 +- .../client/syncadapter/SyncMongoCluster.java | 10 +- .../scala/syncadapter/SyncMongoCluster.scala | 10 +- .../main/com/mongodb/client/MongoCluster.java | 18 +- .../client/internal/MongoClientImpl.java | 10 +- .../client/internal/MongoClusterImpl.java | 10 +- 17 files changed, 191 insertions(+), 229 deletions(-) create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientWriteModelWithNamespace.java diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java index 1357242eef7..2bab92bffd8 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java @@ -26,6 +26,7 @@ import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientWriteModelWithNamespace; import org.bson.Document; import org.bson.conversions.Bson; @@ -39,48 +40,38 @@ @Sealed public interface ClientWriteModel { /** - * Creates a model for inserting the {@code document} into the {@code namespace}. + * Creates a model for inserting the {@code document}. * - * @param namespace The namespace. * @param document The document. * @return The requested model. * @param The document type, for example {@link Document}. * @see Filters */ - static ClientInsertOneModel insertOne( - final MongoNamespace namespace, - final TDocument document) { - notNull("namespace", namespace); + static ClientInsertOneModel insertOne(final TDocument document) { notNull("document", document); - return new ConcreteClientInsertOneModel(namespace, document); + return new ConcreteClientInsertOneModel(document); } /** - * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. - * This method is functionally equivalent to {@link #updateOne(MongoNamespace, Bson, Bson, ClientUpdateOptions)} + * Creates a model for updating at most one document that matches the {@code filter}. + * This method is functionally equivalent to {@link #updateOne(Bson, Bson, ClientUpdateOptions)} * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. * - * @param namespace The namespace. * @param filter The filter. * @param update The update. * @return The requested model. * @see Filters * @see Updates */ - static ClientUpdateOneModel updateOne( - final MongoNamespace namespace, - final Bson filter, - final Bson update) { - notNull("namespace", namespace); + static ClientUpdateOneModel updateOne(final Bson filter, final Bson update) { notNull("filter", filter); notNull("update", update); - return new ConcreteClientUpdateOneModel(namespace, filter, update, null, null); + return new ConcreteClientUpdateOneModel(filter, update, null, null); } /** - * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. + * Creates a model for updating at most one document that matches the {@code filter}. * - * @param namespace The namespace. * @param filter The filter. * @param update The update. * @param options The options. @@ -88,44 +79,33 @@ static ClientUpdateOneModel updateOne( * @see Filters * @see Updates */ - static ClientUpdateOneModel updateOne( - final MongoNamespace namespace, - final Bson filter, - final Bson update, - final ClientUpdateOptions options) { - notNull("namespace", namespace); + static ClientUpdateOneModel updateOne(final Bson filter, final Bson update, final ClientUpdateOptions options) { notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ConcreteClientUpdateOneModel(namespace, filter, update, null, options); + return new ConcreteClientUpdateOneModel(filter, update, null, options); } /** - * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. - * This method is functionally equivalent to {@link #updateOne(MongoNamespace, Bson, Iterable, ClientUpdateOptions)} + * Creates a model for updating at most one document that matches the {@code filter}. + * This method is functionally equivalent to {@link #updateOne(Bson, Iterable, ClientUpdateOptions)} * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. * - * @param namespace The namespace. * @param filter The filter. * @param updatePipeline The update pipeline. * @return The requested model. * @see Filters * @see Aggregates */ - static ClientUpdateOneModel updateOne( - final MongoNamespace namespace, - final Bson filter, - final Iterable updatePipeline) { - notNull("namespace", namespace); + static ClientUpdateOneModel updateOne(final Bson filter, final Iterable updatePipeline) { notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ConcreteClientUpdateOneModel(namespace, filter, null, updatePipeline, null); + return new ConcreteClientUpdateOneModel(filter, null, updatePipeline, null); } /** - * Creates a model for updating at most one document in the {@code namespace} that matches the {@code filter}. + * Creates a model for updating at most one document that matches the {@code filter}. * - * @param namespace The namespace. * @param filter The filter. * @param updatePipeline The update pipeline. * @param options The options. @@ -133,44 +113,33 @@ static ClientUpdateOneModel updateOne( * @see Filters * @see Aggregates */ - static ClientUpdateOneModel updateOne( - final MongoNamespace namespace, - final Bson filter, - final Iterable updatePipeline, - final ClientUpdateOptions options) { - notNull("namespace", namespace); + static ClientUpdateOneModel updateOne(final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ConcreteClientUpdateOneModel(namespace, filter, null, updatePipeline, options); + return new ConcreteClientUpdateOneModel(filter, null, updatePipeline, options); } /** - * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. - * This method is functionally equivalent to {@link #updateMany(MongoNamespace, Bson, Bson, ClientUpdateOptions)} + * Creates a model for updating all documents that match the {@code filter}. + * This method is functionally equivalent to {@link #updateMany(Bson, Bson, ClientUpdateOptions)} * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default}. * - * @param namespace The namespace. * @param filter The filter. * @param update The update. * @return The requested model. * @see Filters * @see Updates */ - static ClientUpdateManyModel updateMany( - final MongoNamespace namespace, - final Bson filter, - final Bson update) { - notNull("namespace", namespace); + static ClientUpdateManyModel updateMany(final Bson filter, final Bson update) { notNull("filter", filter); notNull("update", update); - return new ConcreteClientUpdateManyModel(namespace, filter, update, null, null); + return new ConcreteClientUpdateManyModel(filter, update, null, null); } /** - * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. + * Creates a model for updating all documents that match the {@code filter}. * - * @param namespace The namespace. * @param filter The filter. * @param update The update. * @param options The options. @@ -178,44 +147,33 @@ static ClientUpdateManyModel updateMany( * @see Filters * @see Updates */ - static ClientUpdateManyModel updateMany( - final MongoNamespace namespace, - final Bson filter, - final Bson update, - final ClientUpdateOptions options) { - notNull("namespace", namespace); + static ClientUpdateManyModel updateMany(final Bson filter, final Bson update, final ClientUpdateOptions options) { notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ConcreteClientUpdateManyModel(namespace, filter, update, null, options); + return new ConcreteClientUpdateManyModel(filter, update, null, options); } /** - * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. - * This method is functionally equivalent to {@link #updateMany(MongoNamespace, Bson, Iterable, ClientUpdateOptions)} + * Creates a model for updating all documents that match the {@code filter}. + * This method is functionally equivalent to {@link #updateMany(Bson, Iterable, ClientUpdateOptions)} * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. * - * @param namespace The namespace. * @param filter The filter. * @param updatePipeline The update pipeline. * @return The requested model. * @see Filters * @see Aggregates */ - static ClientUpdateManyModel updateMany( - final MongoNamespace namespace, - final Bson filter, - final Iterable updatePipeline) { - notNull("namespace", namespace); + static ClientUpdateManyModel updateMany(final Bson filter, final Iterable updatePipeline) { notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ConcreteClientUpdateManyModel(namespace, filter, null, updatePipeline, null); + return new ConcreteClientUpdateManyModel(filter, null, updatePipeline, null); } /** - * Creates a model for updating all documents in the {@code namespace} that match the {@code filter}. + * Creates a model for updating all documents that match the {@code filter}. * - * @param namespace The namespace. * @param filter The filter. * @param updatePipeline The update pipeline. * @param options The options. @@ -223,24 +181,18 @@ static ClientUpdateManyModel updateMany( * @see Filters * @see Aggregates */ - static ClientUpdateManyModel updateMany( - final MongoNamespace namespace, - final Bson filter, - final Iterable updatePipeline, - final ClientUpdateOptions options) { - notNull("namespace", namespace); + static ClientUpdateManyModel updateMany(final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ConcreteClientUpdateManyModel(namespace, filter, null, updatePipeline, options); + return new ConcreteClientUpdateManyModel(filter, null, updatePipeline, options); } /** - * Creates a model for replacing at most one document in the {@code namespace} that matches the {@code filter}. - * This method is functionally equivalent to {@link #replaceOne(MongoNamespace, Bson, Object, ClientReplaceOptions)} + * Creates a model for replacing at most one document that matches the {@code filter}. + * This method is functionally equivalent to {@link #replaceOne(Bson, Object, ClientReplaceOptions)} * with the {@linkplain ClientReplaceOptions#clientReplaceOptions() default options}. * - * @param namespace The namespace. * @param filter The filter. * @param replacement The replacement. * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. @@ -248,20 +200,15 @@ static ClientUpdateManyModel updateMany( * @param The document type, for example {@link Document}. * @see Filters */ - static ClientReplaceOneModel replaceOne( - final MongoNamespace namespace, - final Bson filter, - final TDocument replacement) { - notNull("namespace", namespace); + static ClientReplaceOneModel replaceOne(final Bson filter, final TDocument replacement) { notNull("filter", filter); notNull("replacement", replacement); - return new ConcreteClientReplaceOneModel(namespace, filter, replacement, null); + return new ConcreteClientReplaceOneModel(filter, replacement, null); } /** - * Creates a model for replacing at most one document in the {@code namespace} that matches the {@code filter}. + * Creates a model for replacing at most one document that matches the {@code filter}. * - * @param namespace The namespace. * @param filter The filter. * @param replacement The replacement. * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. @@ -270,89 +217,77 @@ static ClientReplaceOneModel replaceOne( * @param The document type, for example {@link Document}. * @see Filters */ - static ClientReplaceOneModel replaceOne( - final MongoNamespace namespace, - final Bson filter, - final TDocument replacement, - final ClientReplaceOptions options) { - notNull("namespace", namespace); + static ClientReplaceOneModel replaceOne(final Bson filter, final TDocument replacement, final ClientReplaceOptions options) { notNull("filter", filter); notNull("replacement", replacement); notNull("options", options); - return new ConcreteClientReplaceOneModel(namespace, filter, replacement, options); + return new ConcreteClientReplaceOneModel(filter, replacement, options); } /** - * Creates a model for removing at most one document from the {@code namespace} that match the {@code filter}. - * This method is functionally equivalent to {@link #deleteOne(MongoNamespace, Bson, ClientDeleteOptions)} + * Creates a model for removing at most one document that match the {@code filter}. + * This method is functionally equivalent to {@link #deleteOne(Bson, ClientDeleteOptions)} * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. * - * @param namespace The namespace. * @param filter The filter. * @return The requested model. * @see Filters */ - static ClientDeleteOneModel deleteOne( - final MongoNamespace namespace, - final Bson filter) { - notNull("namespace", namespace); + static ClientDeleteOneModel deleteOne(final Bson filter) { notNull("filter", filter); - return new ConcreteClientDeleteOneModel(namespace, filter, null); + return new ConcreteClientDeleteOneModel(filter, null); } /** - * Creates a model for removing at most one document from the {@code namespace} that match the {@code filter}. + * Creates a model for removing at most one document that match the {@code filter}. * - * @param namespace The namespace. * @param filter The filter. * @param options The options. * @return The requested model. * @see Filters */ - static ClientDeleteOneModel deleteOne( - final MongoNamespace namespace, - final Bson filter, - final ClientDeleteOptions options) { - notNull("namespace", namespace); + static ClientDeleteOneModel deleteOne(final Bson filter, final ClientDeleteOptions options) { notNull("filter", filter); notNull("options", options); - return new ConcreteClientDeleteOneModel(namespace, filter, options); + return new ConcreteClientDeleteOneModel(filter, options); } /** - * Creates a model for removing all documents from the {@code namespace} that match the {@code filter}. - * This method is functionally equivalent to {@link #deleteMany(MongoNamespace, Bson, ClientDeleteOptions)} + * Creates a model for removing all documents that match the {@code filter}. + * This method is functionally equivalent to {@link #deleteMany(Bson, ClientDeleteOptions)} * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. * - * @param namespace The namespace. * @param filter The filter. * @return The requested model. * @see Filters */ - static ClientDeleteManyModel deleteMany( - final MongoNamespace namespace, - final Bson filter) { - notNull("namespace", namespace); + static ClientDeleteManyModel deleteMany(final Bson filter) { notNull("filter", filter); - return new ConcreteClientDeleteManyModel(namespace, filter, null); + return new ConcreteClientDeleteManyModel(filter, null); } /** - * Creates a model for removing all documents from the {@code namespace} that match the {@code filter}. + * Creates a model for removing all documents that match the {@code filter}. * - * @param namespace The namespace. * @param filter The filter. * @param options The options. * @return The requested model. * @see Filters */ - static ClientDeleteManyModel deleteMany( - final MongoNamespace namespace, - final Bson filter, - final ClientDeleteOptions options) { - notNull("namespace", namespace); + static ClientDeleteManyModel deleteMany(final Bson filter, final ClientDeleteOptions options) { notNull("filter", filter); notNull("options", options); - return new ConcreteClientDeleteManyModel(namespace, filter, options); + return new ConcreteClientDeleteManyModel(filter, options); + } + + /** + * Combines this model with the {@code namespace} it is targeted at. + * + * @param namespace The namespace. + * @return The model with the {@code namespace}. + */ + default ClientWriteModelWithNamespace withNamespace(final MongoNamespace namespace) { + notNull("namespace", namespace); + return new ConcreteClientWriteModelWithNamespace(this, namespace); } } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java new file mode 100644 index 00000000000..d14f5bbf691 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java @@ -0,0 +1,30 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.annotations.Sealed; + +/** + * A combination of an {@linkplain ClientWriteModel individual write operation} and a {@linkplain MongoNamespace namespace} + * the operation is targeted at. + * + * @since 5.3 + */ +@Sealed +public interface ClientWriteModelWithNamespace { +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java index d1164975356..46fe39b489c 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.MongoNamespace; import com.mongodb.client.model.bulk.ClientDeleteManyModel; import com.mongodb.client.model.bulk.ClientDeleteOptions; import com.mongodb.lang.Nullable; @@ -25,17 +24,13 @@ * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientDeleteManyModel extends ConcreteClientDeleteOneModel implements ClientDeleteManyModel { - public ConcreteClientDeleteManyModel( - final MongoNamespace namespace, - final Bson filter, - @Nullable final ClientDeleteOptions options) { - super(namespace, filter, options); + public ConcreteClientDeleteManyModel(final Bson filter, @Nullable final ClientDeleteOptions options) { + super(filter, options); } @Override public String toString() { return "ClientDeleteManyModel{" - + "namespace=" + getNamespace() + ", filter=" + getFilter() + ", options=" + getOptions() + '}'; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java index 666cd37ac59..f002db8f044 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.MongoNamespace; import com.mongodb.client.model.bulk.ClientDeleteOneModel; import com.mongodb.client.model.bulk.ClientDeleteOptions; import com.mongodb.lang.Nullable; @@ -25,23 +24,14 @@ * This class is not part of the public API and may be removed or changed at any time. */ public class ConcreteClientDeleteOneModel implements ClientDeleteOneModel { - private final MongoNamespace namespace; private final Bson filter; private final ConcreteClientDeleteOptions options; - public ConcreteClientDeleteOneModel( - final MongoNamespace namespace, - final Bson filter, - @Nullable final ClientDeleteOptions options) { - this.namespace = namespace; + public ConcreteClientDeleteOneModel(final Bson filter, @Nullable final ClientDeleteOptions options) { this.filter = filter; this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; } - public MongoNamespace getNamespace() { - return namespace; - } - public Bson getFilter() { return filter; } @@ -53,7 +43,6 @@ public ConcreteClientDeleteOptions getOptions() { @Override public String toString() { return "ClientDeleteOneModel{" - + "namespace=" + namespace + ", filter=" + filter + ", options=" + options + '}'; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java index 13ff729e3cf..cea73651c45 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java @@ -15,27 +15,18 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.MongoNamespace; import com.mongodb.client.model.bulk.ClientInsertOneModel; /** * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientInsertOneModel implements ClientInsertOneModel { - private final MongoNamespace namespace; private final Object document; - public ConcreteClientInsertOneModel( - final MongoNamespace namespace, - final Object document) { - this.namespace = namespace; + public ConcreteClientInsertOneModel(final Object document) { this.document = document; } - public MongoNamespace getNamespace() { - return namespace; - } - public Object getDocument() { return document; } @@ -43,7 +34,6 @@ public Object getDocument() { @Override public String toString() { return "ClientInsertOneModel{" - + "namespace=" + namespace + ", document=" + document + '}'; } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java index d3d6fac55b4..608e42ca705 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.MongoNamespace; import com.mongodb.client.model.bulk.ClientReplaceOneModel; import com.mongodb.client.model.bulk.ClientReplaceOptions; import com.mongodb.lang.Nullable; @@ -25,26 +24,16 @@ * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientReplaceOneModel implements ClientReplaceOneModel { - private final MongoNamespace namespace; private final Bson filter; private final Object replacement; private final ConcreteClientReplaceOptions options; - public ConcreteClientReplaceOneModel( - final MongoNamespace namespace, - final Bson filter, - final Object replacement, - @Nullable final ClientReplaceOptions options) { - this.namespace = namespace; + public ConcreteClientReplaceOneModel(final Bson filter, final Object replacement, @Nullable final ClientReplaceOptions options) { this.filter = filter; this.replacement = replacement; this.options = options == null ? ConcreteClientReplaceOptions.MUTABLE_EMPTY : (ConcreteClientReplaceOptions) options; } - public MongoNamespace getNamespace() { - return namespace; - } - public Bson getFilter() { return filter; } @@ -60,7 +49,6 @@ public ConcreteClientReplaceOptions getOptions() { @Override public String toString() { return "ClientReplaceOneModel{" - + "namespace=" + namespace + ", filter=" + filter + ", replacement=" + replacement + ", options=" + options diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java index 2bd6dd023da..a6754342634 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.MongoNamespace; import com.mongodb.assertions.Assertions; import com.mongodb.client.model.bulk.ClientUpdateManyModel; import com.mongodb.client.model.bulk.ClientUpdateOptions; @@ -27,20 +26,18 @@ */ public final class ConcreteClientUpdateManyModel extends ConcreteClientUpdateOneModel implements ClientUpdateManyModel { public ConcreteClientUpdateManyModel( - final MongoNamespace namespace, final Bson filter, @Nullable final Bson update, @Nullable final Iterable updatePipeline, @Nullable final ClientUpdateOptions options) { - super(namespace, filter, update, updatePipeline, options); + super(filter, update, updatePipeline, options); } @Override public String toString() { return "ClientUpdateManyModel{" - + "namespace=" + getNamespace() + ", filter=" + getFilter() + ", update=" + getUpdate().map(Object::toString) .orElse(getUpdatePipeline().map(Object::toString) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java index 54406f888fb..e237fed6608 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.MongoNamespace; import com.mongodb.client.model.bulk.ClientUpdateOneModel; import com.mongodb.client.model.bulk.ClientUpdateOptions; import com.mongodb.lang.Nullable; @@ -30,7 +29,6 @@ * This class is not part of the public API and may be removed or changed at any time. */ public class ConcreteClientUpdateOneModel implements ClientUpdateOneModel { - private final MongoNamespace namespace; private final Bson filter; @Nullable private final Bson update; @@ -39,14 +37,12 @@ public class ConcreteClientUpdateOneModel implements ClientUpdateOneModel { private final ConcreteClientUpdateOptions options; public ConcreteClientUpdateOneModel( - final MongoNamespace namespace, final Bson filter, @Nullable final Bson update, @Nullable final Iterable updatePipeline, @Nullable final ClientUpdateOptions options) { - this.namespace = namespace; this.filter = filter; assertTrue(update == null ^ updatePipeline == null); this.update = update; @@ -54,10 +50,6 @@ public ConcreteClientUpdateOneModel( this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; } - public MongoNamespace getNamespace() { - return namespace; - } - public Bson getFilter() { return filter; } @@ -77,7 +69,6 @@ public ConcreteClientUpdateOptions getOptions() { @Override public String toString() { return "ClientUpdateOneModel{" - + "namespace=" + namespace + ", filter=" + filter + ", update=" + (update != null ? update : updatePipeline) + ", options=" + options diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientWriteModelWithNamespace.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientWriteModelWithNamespace.java new file mode 100644 index 00000000000..10580fe27dc --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientWriteModelWithNamespace.java @@ -0,0 +1,47 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; + +public final class ConcreteClientWriteModelWithNamespace implements ClientWriteModelWithNamespace { + private final ClientWriteModel model; + private final MongoNamespace namespace; + + public ConcreteClientWriteModelWithNamespace(final ClientWriteModel model, final MongoNamespace namespace) { + this.model = model; + this.namespace = namespace; + } + + public ClientWriteModel getModel() { + return model; + } + + public MongoNamespace getNamespace() { + return namespace; + } + + @Override + public String toString() { + return "ClientWriteModelWithNamespace{" + + "model=" + model + + ", namespace=" + namespace + + '}'; + } +} diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt index cd05526a4f3..68904e25a8b 100644 --- a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt @@ -26,7 +26,7 @@ import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable import com.mongodb.client.model.bulk.ClientBulkWriteOptions -import com.mongodb.client.model.bulk.ClientWriteModel +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.coroutine.MongoCluster import java.util.concurrent.TimeUnit @@ -114,12 +114,12 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) - override fun bulkWrite(models: MutableList): ClientBulkWriteResult { + override fun bulkWrite(models: MutableList): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") @@ -127,14 +127,14 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu override fun bulkWrite( clientSession: ClientSession, - models: MutableList + models: MutableList ): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( clientSession: ClientSession, - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt index 6ed8caf2f94..15336a821c9 100644 --- a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt @@ -26,7 +26,7 @@ import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable import com.mongodb.client.model.bulk.ClientBulkWriteOptions -import com.mongodb.client.model.bulk.ClientWriteModel +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.MongoCluster import java.util.concurrent.TimeUnit @@ -113,12 +113,12 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) - override fun bulkWrite(models: MutableList): ClientBulkWriteResult { + override fun bulkWrite(models: MutableList): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") @@ -126,14 +126,14 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu override fun bulkWrite( clientSession: ClientSession, - models: MutableList + models: MutableList ): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( clientSession: ClientSession, - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java index 346f8754085..cd3bd2038cf 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java @@ -29,7 +29,7 @@ import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.reactivestreams.client.internal.BatchCursor; @@ -280,13 +280,13 @@ public void close() { @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels, options); } @@ -294,14 +294,14 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels, options); } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java index f8c15dc4175..105dae471ac 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java @@ -29,7 +29,7 @@ import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import org.bson.BsonDocument; import org.bson.Document; @@ -285,13 +285,13 @@ public ChangeStreamIterable watch(final ClientSession clientS @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @@ -299,14 +299,14 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala index 388f20ed3d3..56b63b7d0f8 100644 --- a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala +++ b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala @@ -1,7 +1,7 @@ package org.mongodb.scala.syncadapter import com.mongodb.assertions.Assertions -import com.mongodb.client.model.bulk.{ ClientBulkWriteOptions, ClientWriteModel } +import com.mongodb.client.model.bulk.{ ClientBulkWriteOptions, ClientWriteModelWithNamespace } import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.{ ClientSessionOptions, ReadConcern, ReadPreference, WriteConcern } import com.mongodb.client.{ ClientSession, MongoCluster => JMongoCluster, MongoDatabase => JMongoDatabase } @@ -129,25 +129,25 @@ class SyncMongoCluster(wrapped: MongoCluster) extends JMongoCluster { clientSession.asInstanceOf[SyncClientSession].wrapped override def bulkWrite( - models: util.List[_ <: ClientWriteModel] + models: util.List[_ <: ClientWriteModelWithNamespace] ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") override def bulkWrite( - models: util.List[_ <: ClientWriteModel], + models: util.List[_ <: ClientWriteModelWithNamespace], options: ClientBulkWriteOptions ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") override def bulkWrite( clientSession: ClientSession, - models: util.List[_ <: ClientWriteModel] + models: util.List[_ <: ClientWriteModelWithNamespace] ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") override def bulkWrite( clientSession: ClientSession, - models: util.List[_ <: ClientWriteModel], + models: util.List[_ <: ClientWriteModelWithNamespace], options: ClientBulkWriteOptions ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index 96ddf95cbea..6bd6e9f26a0 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -30,7 +30,7 @@ import com.mongodb.client.model.bulk.ClientBulkWriteOptions; import com.mongodb.client.model.bulk.ClientDeleteManyModel; import com.mongodb.client.model.bulk.ClientUpdateManyModel; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.lang.Nullable; import org.bson.Document; @@ -372,7 +372,7 @@ public interface MongoCluster { * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* - * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: @@ -383,7 +383,7 @@ public interface MongoCluster { * @mongodb.server.release 8.0 * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ - ClientBulkWriteResult bulkWrite(List models) throws ClientBulkWriteException; + ClientBulkWriteResult bulkWrite(List models) throws ClientBulkWriteException; /** * Executes a client-level bulk write operation. @@ -394,7 +394,7 @@ public interface MongoCluster { * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* - * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. * @param options The options. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, @@ -407,7 +407,7 @@ public interface MongoCluster { * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ ClientBulkWriteResult bulkWrite( - List models, + List models, ClientBulkWriteOptions options) throws ClientBulkWriteException; /** @@ -422,7 +422,7 @@ ClientBulkWriteResult bulkWrite( * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. - * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: @@ -435,7 +435,7 @@ ClientBulkWriteResult bulkWrite( */ ClientBulkWriteResult bulkWrite( ClientSession clientSession, - List models) throws ClientBulkWriteException; + List models) throws ClientBulkWriteException; /** * Executes a client-level bulk write operation. @@ -447,7 +447,7 @@ ClientBulkWriteResult bulkWrite( * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. - * @param models The {@linkplain ClientWriteModel individual write operations}. + * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. * @param options The options. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, @@ -461,6 +461,6 @@ ClientBulkWriteResult bulkWrite( */ ClientBulkWriteResult bulkWrite( ClientSession clientSession, - List models, + List models, ClientBulkWriteOptions options) throws ClientBulkWriteException; } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java index 792e604f182..a3e10121c7f 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java @@ -33,7 +33,7 @@ import com.mongodb.client.MongoIterable; import com.mongodb.client.SynchronousContextProvider; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.connection.SocketSettings; @@ -262,13 +262,13 @@ public ChangeStreamIterable watch( @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels, options); } @@ -276,14 +276,14 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels, options); } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index 1b60d95e2fc..98ffff1ea85 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -40,7 +40,7 @@ import com.mongodb.client.MongoIterable; import com.mongodb.client.SynchronousContextProvider; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.internal.IgnorableRequestContext; import com.mongodb.internal.TimeoutSettings; @@ -314,14 +314,14 @@ public ChangeStreamIterable watch(final ClientSession clientS @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); throw Assertions.fail("BULK-TODO implement"); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); notNull("options", options); @@ -331,7 +331,7 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); throw Assertions.fail("BULK-TODO implement"); @@ -340,7 +340,7 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); From 2ed8e87974442038c859789c38991b97c95a466e Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 8 Aug 2024 11:33:36 -0600 Subject: [PATCH 10/59] Implement JAVA-5528 --- .../com/mongodb/ClientBulkWriteException.java | 19 +- .../operation/AsyncOperationHelper.java | 2 +- .../operation/BsonDocumentWrapperHelper.java | 8 +- .../internal/operation/BulkWriteBatch.java | 6 +- .../operation/ClientBulkWriteOperation.java | 1053 +++++++++++++++++ .../operation/CommandOperationHelper.java | 11 +- .../operation/MixedBulkWriteOperation.java | 8 +- .../internal/operation/Operations.java | 8 + .../operation/SyncOperationHelper.java | 4 +- .../internal/operation/SyncOperations.java | 9 + .../internal/session/SessionContext.java | 2 +- .../validator/UpdateFieldNameValidator.java | 7 +- .../client/internal/MongoClusterImpl.java | 34 +- 13 files changed, 1152 insertions(+), 19 deletions(-) create mode 100644 driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index 1ed748989d7..115051f8c02 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -25,6 +25,8 @@ import java.util.Optional; import static com.mongodb.assertions.Assertions.isTrueArgument; +import static com.mongodb.assertions.Assertions.notNull; +import static com.mongodb.internal.operation.ClientBulkWriteOperation.Exceptions.serverAddressFromException; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.unmodifiableList; @@ -56,6 +58,8 @@ public final class ClientBulkWriteException extends MongoServerException { * @param writeErrors The {@linkplain #getWriteErrors() write errors}. * @param partialResult The {@linkplain #getPartialResult() partial result}. * @param serverAddress The {@linkplain MongoServerException#getServerAddress() server address}. + * If {@code error} is a {@link MongoServerException} or a {@link MongoSocketException}, then {@code serverAddress} + * must be equal to the {@link ServerAddress} they bear. */ public ClientBulkWriteException( @Nullable final MongoException error, @@ -63,9 +67,14 @@ public ClientBulkWriteException( @Nullable final Map writeErrors, @Nullable final ClientBulkWriteResult partialResult, final ServerAddress serverAddress) { - super(message(error, writeConcernErrors, writeErrors, partialResult, serverAddress), serverAddress); + super( + message( + error, writeConcernErrors, writeErrors, partialResult, + notNull("serverAddress", serverAddress)), + validateServerAddress(error, serverAddress)); // BULK-TODO Should ClientBulkWriteException.getCode be the same as error.getCode, // and getErrorLabels/hasErrorLabel contain the same labels as error.getErrorLabels? + // TRANSIENT_TRANSACTION_ERROR_LABEL, UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL, RETRYABLE_WRITE_ERROR_LABEL, NO_WRITES_PERFORMED_ERROR_LABEL isTrueArgument("At least one of `writeConcernErrors`, `writeErrors`, `partialResult` must be non-null or non-empty", !(writeConcernErrors == null || writeConcernErrors.isEmpty()) || !(writeErrors == null || writeErrors.isEmpty()) @@ -89,6 +98,14 @@ private static String message( + (partialResult == null ? "" : " Partial result: " + partialResult + "."); } + private static ServerAddress validateServerAddress(@Nullable final MongoException error, final ServerAddress serverAddress) { + serverAddressFromException(error).ifPresent(serverAddressFromError -> + isTrueArgument("`serverAddress` must be equal to that of the `error`", serverAddressFromError.equals(serverAddress))); + return error instanceof MongoServerException + ? ((MongoServerException) error).getServerAddress() + : serverAddress; + } + /** * The top-level error. That is an error that is neither a {@linkplain #getWriteConcernErrors() write concern error}, * nor is an {@linkplain #getWriteErrors() error of an individual write operation}. diff --git a/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java index b3781fc66ff..ec9240065a8 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java @@ -322,7 +322,7 @@ static AsyncCallbackSupplier decorateReadWithRetriesAsync(final RetryStat static AsyncCallbackSupplier decorateWriteWithRetriesAsync(final RetryState retryState, final OperationContext operationContext, final AsyncCallbackSupplier asyncWriteFunction) { return new RetryingAsyncCallbackSupplier<>(retryState, onRetryableWriteAttemptFailure(operationContext), - CommandOperationHelper::shouldAttemptToRetryWrite, callback -> { + CommandOperationHelper::shouldAttemptToRetryWriteAndAddRetryableLabel, callback -> { logRetryExecute(retryState, operationContext); asyncWriteFunction.get(callback); }); diff --git a/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java b/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java index 5b0d45dfc65..13edabce032 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java @@ -16,6 +16,7 @@ package com.mongodb.internal.operation; +import org.bson.BsonArray; import org.bson.BsonDocument; import org.bson.BsonDocumentWrapper; @@ -25,7 +26,12 @@ final class BsonDocumentWrapperHelper { @SuppressWarnings("unchecked") static List toList(final BsonDocument result, final String fieldContainingWrappedArray) { - return ((BsonArrayWrapper) result.getArray(fieldContainingWrappedArray)).getWrappedArray(); + // BULK-TODO why does the expectation of this code fails? + BsonArray array = result.getArray(fieldContainingWrappedArray); + if (array instanceof BsonArrayWrapper) { + return ((BsonArrayWrapper) array).getWrappedArray(); + } + return (List) array.getValues(); } @SuppressWarnings("unchecked") diff --git a/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java b/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java index 1bca4734eff..84d7dd2c4c0 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java +++ b/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java @@ -111,7 +111,7 @@ static BulkWriteBatch createBulkWriteBatch(final MongoNamespace namespace, } if (canRetryWrites && !writeRequestsAreRetryable) { canRetryWrites = false; - LOGGER.debug("retryWrites set but one or more writeRequests do not support retryable writes"); + logWriteModelDoesNotSupportRetries(); } return new BulkWriteBatch(namespace, connectionDescription, ordered, writeConcern, bypassDocumentValidation, canRetryWrites, new BulkWriteBatchCombiner(connectionDescription.getServerAddress(), ordered, writeConcern), @@ -385,4 +385,8 @@ private static boolean isRetryable(final WriteRequest writeRequest) { } return true; } + + static void logWriteModelDoesNotSupportRetries() { + LOGGER.debug("retryWrites set but one or more writeRequests do not support retryable writes"); + } } diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java new file mode 100644 index 00000000000..69cdba35233 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -0,0 +1,1053 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.operation; + +import com.mongodb.ClientBulkWriteException; +import com.mongodb.Function; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoCommandException; +import com.mongodb.MongoException; +import com.mongodb.MongoNamespace; +import com.mongodb.MongoServerException; +import com.mongodb.MongoSocketException; +import com.mongodb.MongoWriteConcernException; +import com.mongodb.ServerAddress; +import com.mongodb.WriteConcern; +import com.mongodb.WriteError; +import com.mongodb.assertions.Assertions; +import com.mongodb.bulk.WriteConcernError; +import com.mongodb.client.cursor.TimeoutMode; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientDeleteManyModel; +import com.mongodb.client.model.bulk.ClientDeleteOneModel; +import com.mongodb.client.model.bulk.ClientInsertOneModel; +import com.mongodb.client.model.bulk.ClientReplaceOneModel; +import com.mongodb.client.model.bulk.ClientUpdateManyModel; +import com.mongodb.client.model.bulk.ClientUpdateOneModel; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.result.bulk.ClientDeleteResult; +import com.mongodb.client.result.bulk.ClientInsertOneResult; +import com.mongodb.client.result.bulk.ClientUpdateResult; +import com.mongodb.connection.ConnectionDescription; +import com.mongodb.internal.TimeoutContext; +import com.mongodb.internal.async.function.RetryState; +import com.mongodb.internal.binding.ConnectionSource; +import com.mongodb.internal.binding.WriteBinding; +import com.mongodb.internal.client.model.bulk.ConcreteClientBulkWriteOptions; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOptions; +import com.mongodb.internal.client.model.bulk.ConcreteClientInsertOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOptions; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOptions; +import com.mongodb.internal.client.model.bulk.ConcreteClientWriteModelWithNamespace; +import com.mongodb.internal.client.result.bulk.AcknowledgedSummaryClientBulkWriteResult; +import com.mongodb.internal.client.result.bulk.AcknowledgedVerboseClientBulkWriteResult; +import com.mongodb.internal.client.result.bulk.ConcreteClientDeleteResult; +import com.mongodb.internal.client.result.bulk.ConcreteClientInsertOneResult; +import com.mongodb.internal.client.result.bulk.ConcreteClientUpdateResult; +import com.mongodb.internal.client.result.bulk.UnacknowledgedClientBulkWriteResult; +import com.mongodb.internal.connection.Connection; +import com.mongodb.internal.connection.IdHoldingBsonWriter; +import com.mongodb.internal.connection.MongoWriteConcernWithResponseException; +import com.mongodb.internal.connection.OperationContext; +import com.mongodb.internal.operation.retry.AttachmentKeys; +import com.mongodb.internal.session.SessionContext; +import com.mongodb.internal.validator.MappedFieldNameValidator; +import com.mongodb.internal.validator.NoOpFieldNameValidator; +import com.mongodb.internal.validator.ReplacingDocumentFieldNameValidator; +import com.mongodb.internal.validator.UpdateFieldNameValidator; +import com.mongodb.lang.Nullable; +import org.bson.BsonArray; +import org.bson.BsonDocument; +import org.bson.BsonDocumentWrapper; +import org.bson.BsonObjectId; +import org.bson.BsonValue; +import org.bson.BsonWriter; +import org.bson.FieldNameValidator; +import org.bson.codecs.Encoder; +import org.bson.codecs.EncoderContext; +import org.bson.codecs.configuration.CodecRegistry; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static com.mongodb.assertions.Assertions.assertFalse; +import static com.mongodb.assertions.Assertions.assertNotNull; +import static com.mongodb.assertions.Assertions.assertTrue; +import static com.mongodb.assertions.Assertions.fail; +import static com.mongodb.internal.operation.BulkWriteBatch.logWriteModelDoesNotSupportRetries; +import static com.mongodb.internal.operation.CommandOperationHelper.initialRetryState; +import static com.mongodb.internal.operation.CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel; +import static com.mongodb.internal.operation.CommandOperationHelper.transformWriteException; +import static com.mongodb.internal.operation.MixedBulkWriteOperation.commandWriteConcern; +import static com.mongodb.internal.operation.MixedBulkWriteOperation.validateAndGetEffectiveWriteConcern; +import static com.mongodb.internal.operation.OperationHelper.isRetryableWrite; +import static com.mongodb.internal.operation.SyncOperationHelper.cursorDocumentToBatchCursor; +import static com.mongodb.internal.operation.SyncOperationHelper.decorateWriteWithRetries; +import static com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static java.util.Spliterator.IMMUTABLE; +import static java.util.Spliterator.ORDERED; +import static java.util.Spliterators.spliteratorUnknownSize; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.StreamSupport.stream; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ClientBulkWriteOperation implements WriteOperation { + private static final ConcreteClientBulkWriteOptions EMPTY_OPTIONS = new ConcreteClientBulkWriteOptions(); + private static final String BULK_WRITE_COMMAND_NAME = "bulkWrite"; + private static final EncoderContext DEFAULT_ENCODER_CONTEXT = EncoderContext.builder().build(); + private static final EncoderContext COLLECTIBLE_DOCUMENT_ENCODER_CONTEXT = EncoderContext.builder() + .isEncodingCollectibleDocument(true).build(); + + private final List models; + private final ConcreteClientBulkWriteOptions options; + private final WriteConcern writeConcernSetting; + private final boolean retryWritesSetting; + private final CodecRegistry codecRegistry; + + /** + * @param retryWritesSetting See {@link MongoClientSettings#getRetryWrites()}. + */ + public ClientBulkWriteOperation( + final List models, + @Nullable final ClientBulkWriteOptions options, + final WriteConcern writeConcernSetting, + final boolean retryWritesSetting, + final CodecRegistry codecRegistry) { + this.models = models; + this.options = options == null ? EMPTY_OPTIONS : (ConcreteClientBulkWriteOptions) options; + this.writeConcernSetting = writeConcernSetting; + this.retryWritesSetting = retryWritesSetting; + this.codecRegistry = codecRegistry; + } + + @Override + public ClientBulkWriteResult execute(final WriteBinding binding) throws ClientBulkWriteException { + WriteConcern effectiveWriteConcern = validateAndGetEffectiveWriteConcern( + writeConcernSetting, binding.getOperationContext().getSessionContext()); + ResultAccumulator resultAccumulator = new ResultAccumulator(); + MongoException transformedTopLevelError = null; + try { + executeAllBatches(effectiveWriteConcern, binding, resultAccumulator); + } catch (MongoException topLevelError) { + transformedTopLevelError = transformWriteException(topLevelError); + } + return resultAccumulator.build(transformedTopLevelError, effectiveWriteConcern); + } + + /** + * To execute a batch means: + *
    + *
  • execute a `bulkWrite` command, which creates a cursor;
  • + *
  • consume the cursor, which may involve executing `getMore` commands.
  • + *
+ * + * @throws MongoException When a {@linkplain ClientBulkWriteException#getError() top-level error} happens. + */ + private void executeAllBatches( + final WriteConcern effectiveWriteConcern, + final WriteBinding binding, + final ResultAccumulator resultAccumulator) throws MongoException { + Integer nextBatchStartModelIndex = 0; + do { + nextBatchStartModelIndex = executeBatch(nextBatchStartModelIndex, effectiveWriteConcern, binding, resultAccumulator); + } while (nextBatchStartModelIndex != null); + } + + /** + * @return The start model index of the next batch, provided that the operation + * {@linkplain ExhaustiveBulkWriteCommandOkResponse#operationMayContinue(ConcreteClientBulkWriteOptions) may continue} + * and there are unexecuted models left. + */ + @Nullable + private Integer executeBatch( + final int batchStartModelIndex, + final WriteConcern effectiveWriteConcern, + final WriteBinding binding, + final ResultAccumulator resultAccumulator) { + List unexecutedModels = models.subList(batchStartModelIndex, models.size()); + OperationContext operationContext = binding.getOperationContext(); + SessionContext sessionContext = operationContext.getSessionContext(); + TimeoutContext timeoutContext = operationContext.getTimeoutContext(); + RetryState retryState = initialRetryState(retryWritesSetting, timeoutContext); + BatchEncoder batchEncoder = new BatchEncoder(); + Supplier retryingBatchExecutor = decorateWriteWithRetries( + retryState, operationContext, + () -> withSourceAndConnection(binding::getWriteConnectionSource, true, (connectionSource, connection) -> { + ConnectionDescription connectionDescription = connection.getDescription(); + boolean effectiveRetryWrites = isRetryableWrite(retryWritesSetting, effectiveWriteConcern, connectionDescription, sessionContext); + retryState.breakAndThrowIfRetryAnd(() -> !effectiveRetryWrites); + resultAccumulator.onNewServerAddress(connectionDescription.getServerAddress()); + retryState.attach(AttachmentKeys.maxWireVersion(), connectionDescription.getMaxWireVersion(), true) + .attach(AttachmentKeys.commandDescriptionSupplier(), () -> BULK_WRITE_COMMAND_NAME, false); + BsonDocumentWrapper lazilyEncodedBulkWriteCommand = createBulkWriteCommand( + effectiveRetryWrites, effectiveWriteConcern, sessionContext, unexecutedModels, batchEncoder, + () -> retryState.attach(AttachmentKeys.retryableCommandFlag(), true, true)); + return executeBulkWriteCommandAndExhaustOkResponse( + retryState, connectionSource, connection, lazilyEncodedBulkWriteCommand, unexecutedModels, + effectiveWriteConcern, operationContext); + }) + ); + try { + ExhaustiveBulkWriteCommandOkResponse bulkWriteCommandOkResponse = retryingBatchExecutor.get(); + return resultAccumulator.onBulkWriteCommandOkResponseOrNoResponse( + batchStartModelIndex, bulkWriteCommandOkResponse, batchEncoder.intoEncodedBatchInfo()); + } catch (MongoWriteConcernWithResponseException mongoWriteConcernWithOkResponseException) { + return resultAccumulator.onBulkWriteCommandOkResponseWithWriteConcernError( + batchStartModelIndex, mongoWriteConcernWithOkResponseException, batchEncoder.intoEncodedBatchInfo()); + } catch (MongoCommandException bulkWriteCommandException) { + resultAccumulator.onBulkWriteCommandErrorResponse(bulkWriteCommandException); + throw bulkWriteCommandException; + } catch (MongoException e) { + // The server does not have a chance to add "RetryableWriteError" label to `e`, + // and if it is the last attempt failure, `RetryingSyncSupplier` also may not have a chance + // to add the label. So we do that explicitly. + shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, e, false); + resultAccumulator.onBulkWriteCommandErrorWithoutResponse(e); + throw e; + } + } + + /** + * @throws MongoWriteConcernWithResponseException This internal exception must be handled to avoid it being observed by an application. + * It {@linkplain MongoWriteConcernWithResponseException#getResponse() bears} the OK response to the {@code lazilyEncodedCommand}, + * which must be + * {@linkplain ResultAccumulator#onBulkWriteCommandOkResponseWithWriteConcernError(int, MongoWriteConcernWithResponseException, BatchEncoder.EncodedBatchInfo) accumulated} + * iff this exception is the failed result of retries. + */ + @Nullable + private ExhaustiveBulkWriteCommandOkResponse executeBulkWriteCommandAndExhaustOkResponse( + final RetryState retryState, + final ConnectionSource connectionSource, + final Connection connection, + final BsonDocumentWrapper lazilyEncodedCommand, + final List unexecutedModels, + final WriteConcern effectiveWriteConcern, + final OperationContext operationContext) throws MongoWriteConcernWithResponseException { + BsonDocument bulkWriteCommandOkResponse = connection.command( + "admin", + lazilyEncodedCommand, + FieldNameValidators.createUpdateModsFieldValidator(unexecutedModels), + null, + codecRegistry.get(BsonDocument.class), + operationContext, + effectiveWriteConcern.isAcknowledged(), + null, + null); + if (bulkWriteCommandOkResponse == null) { + return null; + } + List> cursorExhaustBatches = doWithRetriesDisabledForCommand(retryState, "getMore", () -> + exhaustBulkWriteCommandOkResponseCursor(connectionSource, connection, bulkWriteCommandOkResponse)); + ExhaustiveBulkWriteCommandOkResponse exhaustiveBulkWriteCommandOkResponse = new ExhaustiveBulkWriteCommandOkResponse( + bulkWriteCommandOkResponse, cursorExhaustBatches); + // `Connection.command` does not throw `MongoWriteConcernException`, so we have to construct it ourselves + MongoWriteConcernException writeConcernException = Exceptions.createWriteConcernException( + bulkWriteCommandOkResponse, connection.getDescription().getServerAddress()); + if (writeConcernException != null) { + throw new MongoWriteConcernWithResponseException(writeConcernException, exhaustiveBulkWriteCommandOkResponse); + } + return exhaustiveBulkWriteCommandOkResponse; + } + + private R doWithRetriesDisabledForCommand( + final RetryState retryState, + final String commandDescription, + final Supplier actionWithCommand) { + Optional originalRetryableCommandFlag = retryState.attachment(AttachmentKeys.retryableCommandFlag()); + Supplier originalCommandDescriptionSupplier = retryState.attachment(AttachmentKeys.commandDescriptionSupplier()) + .orElseThrow(Assertions::fail); + try { + retryState.attach(AttachmentKeys.retryableCommandFlag(), false, true) + .attach(AttachmentKeys.commandDescriptionSupplier(), () -> commandDescription, false); + return actionWithCommand.get(); + } finally { + originalRetryableCommandFlag.ifPresent(value -> retryState.attach(AttachmentKeys.retryableCommandFlag(), value, true)); + retryState.attach(AttachmentKeys.commandDescriptionSupplier(), originalCommandDescriptionSupplier, false); + } + } + + private List> exhaustBulkWriteCommandOkResponseCursor( + final ConnectionSource connectionSource, + final Connection connection, + final BsonDocument response) { + int serverDefaultCursorBatchSize = 0; + try (BatchCursor cursor = cursorDocumentToBatchCursor( + TimeoutMode.CURSOR_LIFETIME, + response, + serverDefaultCursorBatchSize, + codecRegistry.get(BsonDocument.class), + options.getComment().orElse(null), + connectionSource, + connection)) { + return stream(spliteratorUnknownSize(cursor, ORDERED | IMMUTABLE), false).collect(toList()); + } + } + + private BsonDocumentWrapper createBulkWriteCommand( + final boolean effectiveRetryWrites, + final WriteConcern effectiveWriteConcern, + final SessionContext sessionContext, + final List unexecutedModels, + final BatchEncoder batchEncoder, + final Runnable ifCommandIsRetryable) { + // BULK-TODO This implementation must limit the number of `models` it includes in a batch if needed. + // Each batch re-selects a server and re-checks out a connection because this is simpler and it is allowed, + // see https://mongodb.slack.com/archives/C035ZJL6CQN/p1722265720037099?thread_ts=1722264610.664109&cid=C035ZJL6CQN. + return new BsonDocumentWrapper<>( + BULK_WRITE_COMMAND_NAME, + new Encoder() { + @Override + public void encode(final BsonWriter writer, final String commandName, final EncoderContext encoderContext) { + batchEncoder.reset(); + writer.writeStartDocument(); + writer.writeInt32(commandName, 1); + writer.writeBoolean("errorsOnly", !options.isVerboseResults()); + writer.writeBoolean("ordered", options.isOrdered()); + options.isBypassDocumentValidation().ifPresent(value -> writer.writeBoolean("bypassDocumentValidation", value)); + options.getComment().ifPresent(value -> { + writer.writeName("comment"); + encodeUsingRegistry(writer, value); + }); + options.getLet().ifPresent(value -> { + writer.writeName("let"); + encodeUsingRegistry(writer, value); + }); + Function modelSupportsRetries = model -> + !(model instanceof ClientUpdateManyModel || model instanceof ClientDeleteManyModel); + assertFalse(unexecutedModels.isEmpty()); + LinkedHashMap indexedNamespaces = new LinkedHashMap<>(); + writer.writeStartArray("ops"); + boolean commandIsRetryable = effectiveRetryWrites; + for (int modelIndexInBatch = 0; modelIndexInBatch < unexecutedModels.size(); modelIndexInBatch++) { + ConcreteClientWriteModelWithNamespace modelWithNamespace = getModelWithNamespace(unexecutedModels, modelIndexInBatch); + ClientWriteModel model = modelWithNamespace.getModel(); + if (commandIsRetryable && !modelSupportsRetries.apply(model)) { + commandIsRetryable = false; + logWriteModelDoesNotSupportRetries(); + } + MongoNamespace namespace = modelWithNamespace.getNamespace(); + int namespaceIndexInBatch = indexedNamespaces.size(); + Integer existingNamespaceIndex = indexedNamespaces.putIfAbsent(namespace, namespaceIndexInBatch); + namespaceIndexInBatch = existingNamespaceIndex == null ? namespaceIndexInBatch : existingNamespaceIndex; + batchEncoder.encodeWriteModel(writer, model, modelIndexInBatch, namespaceIndexInBatch); + } + writer.writeEndArray(); + writer.writeStartArray("nsInfo"); + indexedNamespaces.keySet().forEach(namespace -> { + writer.writeStartDocument(); + writer.writeString("ns", namespace.getFullName()); + writer.writeEndDocument(); + }); + writer.writeEndArray(); + if (commandIsRetryable) { + batchEncoder.encodeTxnNumber(writer, sessionContext); + ifCommandIsRetryable.run(); + } + commandWriteConcern(effectiveWriteConcern, sessionContext).ifPresent(value -> { + writer.writeName("writeConcern"); + encodeUsingRegistry(writer, value.asDocument()); + }); + writer.writeEndDocument(); + } + + @Override + public Class getEncoderClass() { + throw fail(); + } + } + ); + } + + private void encodeUsingRegistry(final BsonWriter writer, final T value) { + encodeUsingRegistry(writer, value, DEFAULT_ENCODER_CONTEXT); + } + + private void encodeUsingRegistry(final BsonWriter writer, final T value, final EncoderContext encoderContext) { + @SuppressWarnings("unchecked") + Encoder collationEncoder = (Encoder) codecRegistry.get(value.getClass()); + collationEncoder.encode(writer, value, encoderContext); + } + + private static ConcreteClientWriteModelWithNamespace getModelWithNamespace( + final List models, final int index) { + return (ConcreteClientWriteModelWithNamespace) models.get(index); + } + + public static final class Exceptions { + public static Optional serverAddressFromException(@Nullable final MongoException exception) { + ServerAddress serverAddress = null; + if (exception instanceof MongoServerException) { + serverAddress = ((MongoServerException) exception).getServerAddress(); + } else if (exception instanceof MongoSocketException) { + serverAddress = ((MongoSocketException) exception).getServerAddress(); + } + return Optional.ofNullable(serverAddress); + } + + @Nullable + private static MongoWriteConcernException createWriteConcernException( + final BsonDocument response, + final ServerAddress serverAddress) { + final String writeConcernErrorFieldName = "writeConcernError"; + if (!response.containsKey(writeConcernErrorFieldName)) { + return null; + } + BsonDocument writeConcernErrorDocument = response.getDocument(writeConcernErrorFieldName); + WriteConcernError writeConcernError = WriteConcernHelper.createWriteConcernError(writeConcernErrorDocument); + Set errorLabels = response.getArray("errorLabels", new BsonArray()).stream() + .map(i -> i.asString().getValue()) + .collect(toSet()); + return new MongoWriteConcernException(writeConcernError, null, serverAddress, errorLabels); + } + } + + private static final class FieldNameValidators { + /** + * The server supports only the {@code update} individual write operation in the {@code ops} array field, + * while the driver supports {@link ClientUpdateOneModel}, {@link ClientUpdateOneModel}, {@link ClientReplaceOneModel}. + * The difference between updating and replacing is only in the document specified via the {@code updateMods} field: + *
    + *
  • if the name of the first field starts with {@code '$'}, then the document is interpreted as specifying update operators;
  • + *
  • if the name of the first field does not start with {@code '$'}, then the document is interpreted as a replacement.
  • + *
+ */ + private static FieldNameValidator createUpdateModsFieldValidator(final List models) { + return new MappedFieldNameValidator( + NoOpFieldNameValidator.INSTANCE, + singletonMap("ops", new FieldNameValidators.OpsArrayFieldValidator(models))); + } + + static final class OpsArrayFieldValidator implements FieldNameValidator { + private static final Set OPERATION_DISCRIMINATOR_FIELD_NAMES = Stream.of("insert", "update", "delete").collect(toSet()); + + private final List models; + private final ReplacingUpdateModsFieldValidator replacingValidator; + private final UpdatingUpdateModsFieldValidator updatingValidator; + private int currentIndividualOperationIndex; + + OpsArrayFieldValidator(final List models) { + this.models = models; + replacingValidator = new ReplacingUpdateModsFieldValidator(); + updatingValidator = new UpdatingUpdateModsFieldValidator(); + currentIndividualOperationIndex = -1; + } + + @Override + public boolean validate(final String fieldName) { + if (OPERATION_DISCRIMINATOR_FIELD_NAMES.contains(fieldName)) { + currentIndividualOperationIndex++; + } + return true; + } + + @Override + public FieldNameValidator getValidatorForField(final String fieldName) { + if (fieldName.equals("updateMods")) { + return currentIndividualOperationIsReplace() ? replacingValidator.reset() : updatingValidator.reset(); + } + return NoOpFieldNameValidator.INSTANCE; + } + + private boolean currentIndividualOperationIsReplace() { + return getModelWithNamespace(models, currentIndividualOperationIndex).getModel() instanceof ClientReplaceOneModel; + } + } + + private static final class ReplacingUpdateModsFieldValidator implements FieldNameValidator { + private boolean firstFieldSinceLastReset; + + ReplacingUpdateModsFieldValidator() { + firstFieldSinceLastReset = true; + } + + @Override + public boolean validate(final String fieldName) { + if (firstFieldSinceLastReset) { + // we must validate only the first field, and leave the rest up to the server + firstFieldSinceLastReset = false; + return ReplacingDocumentFieldNameValidator.INSTANCE.validate(fieldName); + } + return true; + } + + @Override + public String getValidationErrorMessage(final String fieldName) { + return ReplacingDocumentFieldNameValidator.INSTANCE.getValidationErrorMessage(fieldName); + } + + @Override + public FieldNameValidator getValidatorForField(final String fieldName) { + return NoOpFieldNameValidator.INSTANCE; + } + + ReplacingUpdateModsFieldValidator reset() { + firstFieldSinceLastReset = true; + return this; + } + } + + private static final class UpdatingUpdateModsFieldValidator implements FieldNameValidator { + private final UpdateFieldNameValidator delegate; + private boolean firstFieldSinceLastReset; + + UpdatingUpdateModsFieldValidator() { + delegate = new UpdateFieldNameValidator(); + firstFieldSinceLastReset = true; + } + + @Override + public boolean validate(final String fieldName) { + if (firstFieldSinceLastReset) { + // we must validate only the first field, and leave the rest up to the server + firstFieldSinceLastReset = false; + return delegate.validate(fieldName); + } + return true; + } + + @Override + public String getValidationErrorMessage(final String fieldName) { + return delegate.getValidationErrorMessage(fieldName); + } + + @Override + public FieldNameValidator getValidatorForField(final String fieldName) { + return NoOpFieldNameValidator.INSTANCE; + } + + @Override + public void start() { + delegate.start(); + } + + @Override + public void end() { + delegate.end(); + } + + UpdatingUpdateModsFieldValidator reset() { + delegate.reset(); + firstFieldSinceLastReset = true; + return this; + } + } + } + + private static final class ExhaustiveBulkWriteCommandOkResponse { + /** + * The number of unsuccessful individual write operations. + */ + private final int nErrors; + private final int nInserted; + private final int nUpserted; + private final int nMatched; + private final int nModified; + private final int nDeleted; + private final List cursorExhaust; + + ExhaustiveBulkWriteCommandOkResponse( + final BsonDocument bulkWriteCommandOkResponse, + final List> cursorExhaustBatches) { + this.nErrors = bulkWriteCommandOkResponse.getInt32("nErrors").getValue(); + this.nInserted = bulkWriteCommandOkResponse.getInt32("nInserted").getValue(); + this.nUpserted = bulkWriteCommandOkResponse.getInt32("nUpserted").getValue(); + this.nMatched = bulkWriteCommandOkResponse.getInt32("nMatched").getValue(); + this.nModified = bulkWriteCommandOkResponse.getInt32("nModified").getValue(); + this.nDeleted = bulkWriteCommandOkResponse.getInt32("nDeleted").getValue(); + if (cursorExhaustBatches.isEmpty()) { + cursorExhaust = emptyList(); + } else if (cursorExhaustBatches.size() == 1) { + cursorExhaust = cursorExhaustBatches.get(0); + } else { + cursorExhaust = cursorExhaustBatches.stream().flatMap(Collection::stream).collect(toList()); + } + } + + boolean operationMayContinue(final ConcreteClientBulkWriteOptions options) { + return nErrors == 0 || !options.isOrdered(); + } + + int getNErrors() { + return nErrors; + } + + int getNInserted() { + return nInserted; + } + + int getNUpserted() { + return nUpserted; + } + + int getNMatched() { + return nMatched; + } + + int getNModified() { + return nModified; + } + + int getNDeleted() { + return nDeleted; + } + + List getCursorExhaust() { + return cursorExhaust; + } + } + + /** + * Accumulates results of the operation as it is being executed + * for {@linkplain #build(MongoException, WriteConcern) building} them when the operation completes. + */ + private final class ResultAccumulator { + @Nullable + private ServerAddress serverAddress; + private final ArrayList batchResults; + + ResultAccumulator() { + serverAddress = null; + batchResults = new ArrayList<>(); + } + + /** + *
    + *
  • Either builds and returns {@link ClientBulkWriteResult};
  • + *
  • or builds and throws {@link ClientBulkWriteException};
  • + *
  • or throws {@code topLevelError}.
  • + *
+ */ + ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final WriteConcern effectiveWriteConcern) throws MongoException { + boolean verboseResultsSetting = options.isVerboseResults(); + boolean haveResponses = false; + boolean haveSuccessfulIndividualOperations = false; + long insertedCount = 0; + long upsertedCount = 0; + long matchedCount = 0; + long modifiedCount = 0; + long deletedCount = 0; + Map insertResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); + Map updateResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); + Map deleteResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); + ArrayList writeConcernErrors = new ArrayList<>(); + Map writeErrors = new HashMap<>(); + for (BatchResult batchResult : batchResults) { + if (batchResult.hasResponse()) { + haveResponses = true; + MongoWriteConcernException writeConcernException = batchResult.getWriteConcernException(); + if (writeConcernException != null) { + writeConcernErrors.add(writeConcernException.getWriteConcernError()); + } + int batchStartModelIndex = batchResult.getBatchStartModelIndex(); + ExhaustiveBulkWriteCommandOkResponse response = batchResult.getResponse(); + haveSuccessfulIndividualOperations = haveSuccessfulIndividualOperations + || response.getNErrors() < batchResult.getBatchModelsCount(); + insertedCount += response.getNInserted(); + upsertedCount += response.getNUpserted(); + matchedCount += response.getNMatched(); + modifiedCount += response.getNModified(); + deletedCount += response.getNDeleted(); + Map insertModelDocumentIds = batchResult.getInsertModelDocumentIds(); + for (BsonDocument individualOperationResponse : response.getCursorExhaust()) { + int individualOperationIndexInBatch = individualOperationResponse.getInt32("idx").getValue(); + int writeModelIndexInBatch = batchStartModelIndex + individualOperationIndexInBatch; + if (individualOperationResponse.getNumber("ok").intValue() == 1) { + assertTrue(verboseResultsSetting); + ClientWriteModel writeModel = getModelWithNamespace(models, writeModelIndexInBatch).getModel(); + if (writeModel instanceof ClientInsertOneModel) { + insertResults.put( + (long) writeModelIndexInBatch, + new ConcreteClientInsertOneResult(insertModelDocumentIds.get(individualOperationIndexInBatch))); + } else if (writeModel instanceof ClientUpdateOneModel || writeModel instanceof ClientReplaceOneModel) { + BsonDocument upsertedIdDocument = individualOperationResponse.getDocument("upserted", null); + updateResults.put( + (long) writeModelIndexInBatch, + new ConcreteClientUpdateResult( + individualOperationResponse.getInt32("n").getValue(), + individualOperationResponse.getInt32("nModified").getValue(), + upsertedIdDocument == null ? null : upsertedIdDocument.get("_id"))); + } else if (writeModel instanceof ClientDeleteOneModel) { + deleteResults.put( + (long) writeModelIndexInBatch, + new ConcreteClientDeleteResult(individualOperationResponse.getInt32("n").getValue())); + } else { + fail(writeModel.getClass().toString()); + } + } else { + WriteError individualOperationWriteError = new WriteError( + individualOperationResponse.getInt32("code").getValue(), + individualOperationResponse.getString("errmsg").getValue(), + individualOperationResponse.getDocument("errInfo", new BsonDocument())); + writeErrors.put((long) writeModelIndexInBatch, individualOperationWriteError); + } + } + } + } + if (topLevelError == null && writeConcernErrors.isEmpty() && writeErrors.isEmpty()) { + if (effectiveWriteConcern.isAcknowledged()) { + AcknowledgedSummaryClientBulkWriteResult summaryResult = new AcknowledgedSummaryClientBulkWriteResult( + insertedCount, upsertedCount, matchedCount, modifiedCount, deletedCount); + return verboseResultsSetting + ? new AcknowledgedVerboseClientBulkWriteResult(summaryResult, insertResults, updateResults, deleteResults) + : summaryResult; + } else { + return UnacknowledgedClientBulkWriteResult.INSTANCE; + } + } else if (haveResponses) { + AcknowledgedSummaryClientBulkWriteResult partialSummaryResult = haveSuccessfulIndividualOperations + ? new AcknowledgedSummaryClientBulkWriteResult(insertedCount, upsertedCount, matchedCount, modifiedCount, deletedCount) + : null; + throw new ClientBulkWriteException( + topLevelError, + writeConcernErrors, + writeErrors, + verboseResultsSetting && partialSummaryResult != null + ? new AcknowledgedVerboseClientBulkWriteResult(partialSummaryResult, insertResults, updateResults, deleteResults) + : partialSummaryResult, + assertNotNull(serverAddress)); + } else { + throw assertNotNull(topLevelError); + } + } + + void onNewServerAddress(final ServerAddress serverAddress) { + this.serverAddress = serverAddress; + } + + @Nullable + Integer onBulkWriteCommandOkResponseOrNoResponse( + final int batchStartModelIndex, + @Nullable + final ExhaustiveBulkWriteCommandOkResponse response, + final BatchEncoder.EncodedBatchInfo encodedBatchInfo) { + return onBulkWriteCommandOkResponseOrNoResponse(batchStartModelIndex, response, null, encodedBatchInfo); + } + + /** + * @return See {@link #executeBatch(int, WriteConcern, WriteBinding, ResultAccumulator)}. + */ + @Nullable + Integer onBulkWriteCommandOkResponseWithWriteConcernError( + final int batchStartModelIndex, + final MongoWriteConcernWithResponseException exception, + final BatchEncoder.EncodedBatchInfo encodedBatchInfo) { + MongoWriteConcernException writeConcernException = (MongoWriteConcernException) exception.getCause(); + onNewServerAddress(writeConcernException.getServerAddress()); + ExhaustiveBulkWriteCommandOkResponse response = (ExhaustiveBulkWriteCommandOkResponse) exception.getResponse(); + return onBulkWriteCommandOkResponseOrNoResponse(batchStartModelIndex, response, writeConcernException, encodedBatchInfo); + } + + /** + * @return See {@link #executeBatch(int, WriteConcern, WriteBinding, ResultAccumulator)}. + */ + @Nullable + private Integer onBulkWriteCommandOkResponseOrNoResponse( + final int batchStartModelIndex, + @Nullable + final ExhaustiveBulkWriteCommandOkResponse response, + @Nullable + final MongoWriteConcernException writeConcernException, + final BatchEncoder.EncodedBatchInfo encodedBatchInfo) { + BatchResult batchResult = response == null + ? BatchResult.noResponse(batchStartModelIndex, encodedBatchInfo) + : BatchResult.okResponse(batchStartModelIndex, encodedBatchInfo, response, writeConcernException); + batchResults.add(batchResult); + int potentialNextBatchStartModelIndex = batchStartModelIndex + batchResult.getBatchModelsCount(); + return (response == null || response.operationMayContinue(options)) + ? potentialNextBatchStartModelIndex == models.size() ? null : potentialNextBatchStartModelIndex + : null; + } + + void onBulkWriteCommandErrorResponse(final MongoCommandException exception) { + onNewServerAddress(exception.getServerAddress()); + } + + void onBulkWriteCommandErrorWithoutResponse(final MongoException exception) { + Exceptions.serverAddressFromException(exception).ifPresent(this::onNewServerAddress); + } + } + + static final class BatchResult { + private final int batchStartModelIndex; + private final BatchEncoder.EncodedBatchInfo encodedBatchInfo; + @Nullable + private final ExhaustiveBulkWriteCommandOkResponse response; + @Nullable + private final MongoWriteConcernException writeConcernException; + + static BatchResult okResponse( + final int batchStartModelIndex, + final BatchEncoder.EncodedBatchInfo encodedBatchInfo, + final ExhaustiveBulkWriteCommandOkResponse response, + @Nullable final MongoWriteConcernException writeConcernException) { + return new BatchResult(batchStartModelIndex, encodedBatchInfo, assertNotNull(response), writeConcernException); + } + + static BatchResult noResponse(final int batchStartModelIndex, final BatchEncoder.EncodedBatchInfo encodedBatchInfo) { + return new BatchResult(batchStartModelIndex, encodedBatchInfo, null, null); + } + + private BatchResult( + final int batchStartModelIndex, + final BatchEncoder.EncodedBatchInfo encodedBatchInfo, + @Nullable final ExhaustiveBulkWriteCommandOkResponse response, + @Nullable final MongoWriteConcernException writeConcernException) { + this.batchStartModelIndex = batchStartModelIndex; + this.encodedBatchInfo = encodedBatchInfo; + this.response = response; + this.writeConcernException = writeConcernException; + } + + int getBatchStartModelIndex() { + return batchStartModelIndex; + } + + /** + * @see BatchEncoder.EncodedBatchInfo#getModelsCount() + */ + int getBatchModelsCount() { + return encodedBatchInfo.getModelsCount(); + } + + boolean hasResponse() { + return response != null; + } + + ExhaustiveBulkWriteCommandOkResponse getResponse() { + return assertNotNull(response); + } + + @Nullable + MongoWriteConcernException getWriteConcernException() { + assertTrue(hasResponse()); + return writeConcernException; + } + + /** + * @see BatchEncoder.EncodedBatchInfo#getInsertModelDocumentIds() + */ + Map getInsertModelDocumentIds() { + assertTrue(hasResponse()); + return encodedBatchInfo.getInsertModelDocumentIds(); + } + } + + /** + * Exactly one instance must be used per {@linkplain #executeBatch(int, WriteConcern, WriteBinding, ResultAccumulator) batch}. + */ + private final class BatchEncoder { + private EncodedBatchInfo encodedBatchInfo; + + BatchEncoder() { + encodedBatchInfo = new EncodedBatchInfo(); + } + + /** + * Must be called at most once. + * Must not be called before calling {@link #encodeWriteModel(BsonWriter, ClientWriteModel, int, int)} at least once. + * Renders {@code this} unusable. + */ + EncodedBatchInfo intoEncodedBatchInfo() { + EncodedBatchInfo result = assertNotNull(encodedBatchInfo); + encodedBatchInfo = null; + assertTrue(result.getModelsCount() > 0); + return result; + } + + void reset() { + // we must not reset anything but `modelsCount` + assertNotNull(encodedBatchInfo).modelsCount = 0; + } + + void encodeTxnNumber(final BsonWriter writer, final SessionContext sessionContext) { + EncodedBatchInfo localEncodedBatchInfo = assertNotNull(encodedBatchInfo); + if (localEncodedBatchInfo.txnNumber == EncodedBatchInfo.UNINITIALIZED_TXN_NUMBER) { + localEncodedBatchInfo.txnNumber = sessionContext.advanceTransactionNumber(); + } + writer.writeInt64("txnNumber", localEncodedBatchInfo.txnNumber); + } + + void encodeWriteModel( + final BsonWriter writer, + final ClientWriteModel model, + final int modelIndexInBatch, + final int namespaceIndexInBatch) { + assertNotNull(encodedBatchInfo).modelsCount++; + writer.writeStartDocument(); + if (model instanceof ConcreteClientInsertOneModel) { + writer.writeInt32("insert", namespaceIndexInBatch); + encodeWriteModelInternals(writer, (ConcreteClientInsertOneModel) model, modelIndexInBatch); + } else if (model instanceof ConcreteClientUpdateManyModel) { + writer.writeInt32("update", namespaceIndexInBatch); + encodeWriteModelInternals(writer, (ConcreteClientUpdateManyModel) model); + } else if (model instanceof ConcreteClientUpdateOneModel) { + writer.writeInt32("update", namespaceIndexInBatch); + encodeWriteModelInternals(writer, (ConcreteClientUpdateOneModel) model); + } else if (model instanceof ConcreteClientReplaceOneModel) { + writer.writeInt32("update", namespaceIndexInBatch); + encodeWriteModelInternals(writer, (ConcreteClientReplaceOneModel) model); + } else if (model instanceof ConcreteClientDeleteManyModel) { + writer.writeInt32("delete", namespaceIndexInBatch); + encodeWriteModelInternals(writer, (ConcreteClientDeleteManyModel) model); + } else if (model instanceof ConcreteClientDeleteOneModel) { + writer.writeInt32("delete", namespaceIndexInBatch); + encodeWriteModelInternals(writer, (ConcreteClientDeleteOneModel) model); + } else { + throw fail(model.getClass().toString()); + } + writer.writeEndDocument(); + } + + private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientInsertOneModel model, final int modelIndexInBatch) { + writer.writeName("document"); + Object document = model.getDocument(); + @SuppressWarnings("unchecked") + Encoder documentEncoder = (Encoder) codecRegistry.get(document.getClass()); + assertNotNull(encodedBatchInfo).insertModelDocumentIds.compute(modelIndexInBatch, (k, knownModelDocumentId) -> { + IdHoldingBsonWriter documentIdHoldingBsonWriter = new IdHoldingBsonWriter( + writer, + // Reuse `knownModelDocumentId` if it may have been generated by `IdHoldingBsonWriter` in a previous attempt. + // If its type is not `BsonObjectId`, we know it could not have been generated. + knownModelDocumentId instanceof BsonObjectId ? knownModelDocumentId.asObjectId() : null); + documentEncoder.encode(documentIdHoldingBsonWriter, document, COLLECTIBLE_DOCUMENT_ENCODER_CONTEXT); + return documentIdHoldingBsonWriter.getId(); + }); + } + + private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientUpdateManyModel model) { + encodeWriteModelInternals(writer, (ConcreteClientUpdateOneModel) model); + } + + private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientUpdateOneModel model) { + writer.writeBoolean("multi", model instanceof ConcreteClientUpdateManyModel); + writer.writeName("filter"); + encodeUsingRegistry(writer, model.getFilter()); + model.getUpdate().ifPresent(value -> { + writer.writeName("updateMods"); + encodeUsingRegistry(writer, value); + }); + model.getUpdatePipeline().ifPresent(value -> { + writer.writeStartArray("updateMods"); + value.forEach(pipelineStage -> encodeUsingRegistry(writer, pipelineStage)); + writer.writeEndArray(); + }); + ConcreteClientUpdateOptions options = model.getOptions(); + options.getArrayFilters().ifPresent(value -> { + writer.writeStartArray("arrayFilters"); + value.forEach(filter -> encodeUsingRegistry(writer, filter)); + writer.writeEndArray(); + }); + options.getCollation().ifPresent(value -> { + writer.writeName("collation"); + encodeUsingRegistry(writer, value.asDocument()); + }); + options.getHint().ifPresent(hint -> { + writer.writeName("hint"); + encodeUsingRegistry(writer, hint); + }); + options.getHintString().ifPresent(value -> writer.writeString("hint", value)); + options.isUpsert().ifPresent(value -> writer.writeBoolean("upsert", value)); + } + + private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientReplaceOneModel model) { + writer.writeBoolean("multi", false); + writer.writeName("filter"); + encodeUsingRegistry(writer, model.getFilter()); + writer.writeName("updateMods"); + encodeUsingRegistry(writer, model.getReplacement(), COLLECTIBLE_DOCUMENT_ENCODER_CONTEXT); + ConcreteClientReplaceOptions options = model.getOptions(); + options.getCollation().ifPresent(value -> { + writer.writeName("collation"); + encodeUsingRegistry(writer, value.asDocument()); + }); + options.getHint().ifPresent(value -> { + writer.writeName("hint"); + encodeUsingRegistry(writer, value); + }); + options.getHintString().ifPresent(value -> writer.writeString("hint", value)); + options.isUpsert().ifPresent(value -> writer.writeBoolean("upsert", value)); + } + + private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientDeleteManyModel model) { + encodeWriteModelInternals(writer, (ConcreteClientDeleteOneModel) model); + } + + private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientDeleteOneModel model) { + writer.writeBoolean("multi", model instanceof ConcreteClientDeleteManyModel); + writer.writeName("filter"); + encodeUsingRegistry(writer, model.getFilter()); + ConcreteClientDeleteOptions options = model.getOptions(); + options.getCollation().ifPresent(value -> { + writer.writeName("collation"); + encodeUsingRegistry(writer, value.asDocument()); + }); + options.getHint().ifPresent(value -> { + writer.writeName("hint"); + encodeUsingRegistry(writer, value); + }); + options.getHintString().ifPresent(value -> writer.writeString("hint", value)); + } + + final class EncodedBatchInfo { + private static final long UNINITIALIZED_TXN_NUMBER = -1; + + private long txnNumber; + private final HashMap insertModelDocumentIds; + private int modelsCount; + + private EncodedBatchInfo() { + insertModelDocumentIds = new HashMap<>(); + modelsCount = 0; + txnNumber = UNINITIALIZED_TXN_NUMBER; + } + + /** + * The key of each entry is the index of a model in the + * {@linkplain #executeBatch(int, WriteConcern, WriteBinding, ResultAccumulator) batch}, + * the value is either the "_id" field value from {@linkplain ConcreteClientInsertOneModel#getDocument()}, + * or the value we generated for this field if the field is absent. + */ + Map getInsertModelDocumentIds() { + return insertModelDocumentIds; + } + + int getModelsCount() { + return modelsCount; + } + } + } +} diff --git a/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java index 4c428131853..4a2ee10e29a 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java @@ -153,7 +153,14 @@ static boolean shouldAttemptToRetryRead(final RetryState retryState, final Throw return decision; } - static boolean shouldAttemptToRetryWrite(final RetryState retryState, final Throwable attemptFailure) { + static boolean shouldAttemptToRetryWriteAndAddRetryableLabel(final RetryState retryState, final Throwable attemptFailure) { + return shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, attemptFailure, true); + } + + static boolean shouldAttemptToRetryWriteAndAddRetryableLabel( + final RetryState retryState, + final Throwable attemptFailure, + final boolean logIfDecideToNotRetry) { Throwable failure = attemptFailure instanceof ResourceSupplierInternalException ? attemptFailure.getCause() : attemptFailure; boolean decision = false; MongoException exceptionRetryableRegardlessOfCommand = null; @@ -170,7 +177,7 @@ static boolean shouldAttemptToRetryWrite(final RetryState retryState, final Thro } else if (decideRetryableAndAddRetryableWriteErrorLabel(failure, retryState.attachment(AttachmentKeys.maxWireVersion()) .orElse(null))) { decision = true; - } else { + } else if (logIfDecideToNotRetry) { logUnableToRetry(retryState.attachment(AttachmentKeys.commandDescriptionSupplier()).orElse(null), failure); } } diff --git a/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java index a32ce6d5153..01b1e362315 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java @@ -164,7 +164,7 @@ private boolean shouldAttemptToRetryWrite(final RetryState retryState, final Thr if (bulkWriteTracker.lastAttempt()) { return false; } - boolean decision = CommandOperationHelper.shouldAttemptToRetryWrite(retryState, attemptFailure); + boolean decision = CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, attemptFailure); if (decision) { /* The attempt counter maintained by `RetryState` is updated after (in the happens-before order) testing a retry predicate, * and only if the predicate completes normally. Here we maintain attempt counters manually, and we emulate the @@ -274,7 +274,7 @@ private BulkWriteResult executeBulkWriteBatch( if (currentBulkWriteTracker.lastAttempt()) { addRetryableWriteErrorLabel(writeConcernBasedError, maxWireVersion); addErrorLabelsToWriteConcern(result.getDocument("writeConcernError"), writeConcernBasedError.getErrorLabels()); - } else if (CommandOperationHelper.shouldAttemptToRetryWrite(retryState, writeConcernBasedError)) { + } else if (CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, writeConcernBasedError)) { throw new MongoWriteConcernWithResponseException(writeConcernBasedError, result); } } @@ -328,7 +328,7 @@ private void executeBulkWriteBatchAsync( addRetryableWriteErrorLabel(writeConcernBasedError, maxWireVersion); addErrorLabelsToWriteConcern(result.getDocument("writeConcernError"), writeConcernBasedError.getErrorLabels()); - } else if (CommandOperationHelper.shouldAttemptToRetryWrite(retryState, writeConcernBasedError)) { + } else if (CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, writeConcernBasedError)) { iterationCallback.onResult(null, new MongoWriteConcernWithResponseException(writeConcernBasedError, result)); return; @@ -435,7 +435,7 @@ operationContext, shouldExpectResponse(batch, effectiveWriteConcern), batch.getPayload(), batch.getFieldNameValidator(), callback); } - private static WriteConcern validateAndGetEffectiveWriteConcern(final WriteConcern writeConcernSetting, final SessionContext sessionContext) + static WriteConcern validateAndGetEffectiveWriteConcern(final WriteConcern writeConcernSetting, final SessionContext sessionContext) throws MongoClientException { boolean activeTransaction = sessionContext.hasActiveTransaction(); WriteConcern effectiveWriteConcern = activeTransaction diff --git a/driver-core/src/main/com/mongodb/internal/operation/Operations.java b/driver-core/src/main/com/mongodb/internal/operation/Operations.java index 5ec696b61ce..4d4170bb5d3 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/Operations.java +++ b/driver-core/src/main/com/mongodb/internal/operation/Operations.java @@ -54,6 +54,8 @@ import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.model.ValidationOptions; import com.mongodb.client.model.WriteModel; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocumentBeforeChange; import com.mongodb.internal.bulk.DeleteRequest; @@ -718,6 +720,12 @@ ChangeStreamOperation changeStream(final FullDocument fullDoc .retryReads(retryReads); } + ClientBulkWriteOperation clientBulkWriteOperation( + final List clientWriteModels, + @Nullable final ClientBulkWriteOptions options) { + return new ClientBulkWriteOperation(clientWriteModels, options, writeConcern, retryWrites, codecRegistry); + } + private Codec getCodec() { return codecRegistry.get(documentClass); } diff --git a/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java index 62da7cde2c8..b689a5aedd2 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java @@ -303,7 +303,7 @@ static T createReadCommandAndExecute( static Supplier decorateWriteWithRetries(final RetryState retryState, final OperationContext operationContext, final Supplier writeFunction) { return new RetryingSyncSupplier<>(retryState, onRetryableWriteAttemptFailure(operationContext), - CommandOperationHelper::shouldAttemptToRetryWrite, () -> { + CommandOperationHelper::shouldAttemptToRetryWriteAndAddRetryableLabel, () -> { logRetryExecute(retryState, operationContext); return writeFunction.get(); }); @@ -335,7 +335,7 @@ static CommandReadTransformer> singleBatchCurso } static BatchCursor cursorDocumentToBatchCursor(final TimeoutMode timeoutMode, final BsonDocument cursorDocument, - final int batchSize, final Decoder decoder, final BsonValue comment, final ConnectionSource source, + final int batchSize, final Decoder decoder, @Nullable final BsonValue comment, final ConnectionSource source, final Connection connection) { return new CommandBatchCursor<>(timeoutMode, cursorDocument, batchSize, 0, decoder, comment, source, connection); } diff --git a/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java b/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java index 73a83310d65..7f62cdba1f2 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java +++ b/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java @@ -44,8 +44,11 @@ import com.mongodb.client.model.SearchIndexModel; import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.model.WriteModel; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocumentBeforeChange; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.internal.TimeoutSettings; import com.mongodb.internal.client.model.AggregationLevel; import com.mongodb.internal.client.model.FindOptions; @@ -358,4 +361,10 @@ public ReadOperation> changeStream(final FullDocu return operations.changeStream(fullDocument, fullDocumentBeforeChange, pipeline, decoder, changeStreamLevel, batchSize, collation, comment, resumeToken, startAtOperationTime, startAfter, showExpandedEvents); } + + public WriteOperation clientBulkWriteOperation( + final List clientWriteModels, + @Nullable final ClientBulkWriteOptions options) { + return operations.clientBulkWriteOperation(clientWriteModels, options); + } } diff --git a/driver-core/src/main/com/mongodb/internal/session/SessionContext.java b/driver-core/src/main/com/mongodb/internal/session/SessionContext.java index 6c55c526d45..4a8902799ec 100644 --- a/driver-core/src/main/com/mongodb/internal/session/SessionContext.java +++ b/driver-core/src/main/com/mongodb/internal/session/SessionContext.java @@ -48,7 +48,7 @@ public interface SessionContext { /** * Advance the transaction number. * - * @return the next transaction number for the session + * @return the next non-negative transaction number for the session */ long advanceTransactionNumber(); diff --git a/driver-core/src/main/com/mongodb/internal/validator/UpdateFieldNameValidator.java b/driver-core/src/main/com/mongodb/internal/validator/UpdateFieldNameValidator.java index 40762bfb5fb..fc59b0cc312 100644 --- a/driver-core/src/main/com/mongodb/internal/validator/UpdateFieldNameValidator.java +++ b/driver-core/src/main/com/mongodb/internal/validator/UpdateFieldNameValidator.java @@ -48,7 +48,7 @@ public FieldNameValidator getValidatorForField(final String fieldName) { @Override public void start() { - encounteredField = false; + reset(); } @Override @@ -57,4 +57,9 @@ public void end() { throw new IllegalArgumentException("Invalid BSON document for an update. The document may not be empty."); } } + + public UpdateFieldNameValidator reset() { + encounteredField = false; + return this; + } } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index 98ffff1ea85..5d5ad85e452 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -31,7 +31,6 @@ import com.mongodb.ServerApi; import com.mongodb.TransactionOptions; import com.mongodb.WriteConcern; -import com.mongodb.assertions.Assertions; import com.mongodb.client.ChangeStreamIterable; import com.mongodb.client.ClientSession; import com.mongodb.client.ListDatabasesIterable; @@ -54,6 +53,7 @@ import com.mongodb.internal.connection.OperationContext; import com.mongodb.internal.connection.ReadConcernAwareNoOpSessionContext; import com.mongodb.internal.operation.ReadOperation; +import com.mongodb.internal.operation.SyncOperations; import com.mongodb.internal.operation.WriteOperation; import com.mongodb.internal.session.ServerSessionPool; import com.mongodb.lang.Nullable; @@ -72,6 +72,7 @@ import static com.mongodb.MongoException.UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL; import static com.mongodb.ReadPreference.primary; import static com.mongodb.assertions.Assertions.isTrue; +import static com.mongodb.assertions.Assertions.isTrueArgument; import static com.mongodb.assertions.Assertions.notNull; import static com.mongodb.internal.TimeoutContext.createTimeoutContext; @@ -96,6 +97,7 @@ final class MongoClusterImpl implements MongoCluster { private final TimeoutSettings timeoutSettings; private final UuidRepresentation uuidRepresentation; private final WriteConcern writeConcern; + private final SyncOperations operations; MongoClusterImpl( @Nullable final AutoEncryptionSettings autoEncryptionSettings, final Cluster cluster, final CodecRegistry codecRegistry, @@ -120,6 +122,16 @@ final class MongoClusterImpl implements MongoCluster { this.timeoutSettings = timeoutSettings; this.uuidRepresentation = uuidRepresentation; this.writeConcern = writeConcern; + operations = new SyncOperations<>( + null, + BsonDocument.class, + readPreference, + codecRegistry, + readConcern, + writeConcern, + retryWrites, + retryReads, + timeoutSettings); } @Override @@ -316,7 +328,8 @@ public ChangeStreamIterable watch(final ClientSession clientS public ClientBulkWriteResult bulkWrite( final List clientWriteModels) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); - throw Assertions.fail("BULK-TODO implement"); + isTrueArgument("`clientWriteModels` must not be empty", !clientWriteModels.isEmpty()); + return executeBulkWrite(null, clientWriteModels, null); } @Override @@ -324,8 +337,9 @@ public ClientBulkWriteResult bulkWrite( final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); + isTrueArgument("`clientWriteModels` must not be empty", !clientWriteModels.isEmpty()); notNull("options", options); - throw Assertions.fail("BULK-TODO implement"); + return executeBulkWrite(null, clientWriteModels, options); } @Override @@ -334,7 +348,8 @@ public ClientBulkWriteResult bulkWrite( final List clientWriteModels) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); - throw Assertions.fail("BULK-TODO implement"); + isTrueArgument("`clientWriteModels` must not be empty", !clientWriteModels.isEmpty()); + return executeBulkWrite(clientSession, clientWriteModels, null); } @Override @@ -344,8 +359,9 @@ public ClientBulkWriteResult bulkWrite( final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); + isTrueArgument("`clientWriteModels` must not be empty", !clientWriteModels.isEmpty()); notNull("options", options); - throw Assertions.fail("BULK-TODO implement"); + return executeBulkWrite(clientSession, clientWriteModels, options); } private ListDatabasesIterable createListDatabasesIterable(@Nullable final ClientSession clientSession, final Class clazz) { @@ -365,6 +381,14 @@ private ChangeStreamIterable createChangeStreamIterable(@Null retryReads, timeoutSettings); } + private ClientBulkWriteResult executeBulkWrite( + @Nullable final ClientSession clientSession, + final List clientWriteModels, + @Nullable final ClientBulkWriteOptions options) { + isTrue("`autoEncryptionSettings` is null, as automatic encryption is not yet supported", autoEncryptionSettings == null); + return operationExecutor.execute(operations.clientBulkWriteOperation(clientWriteModels, options), readConcern, clientSession); + } + final class OperationExecutorImpl implements OperationExecutor { private final TimeoutSettings executorTimeoutSettings; From 07bac957db70ff7479e34f2d79ce7e294cd6cae8 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 15 Aug 2024 16:50:56 -0600 Subject: [PATCH 11/59] Sync spec tests JAVA-5528 --- .../unacknowledged-client-bulkWrite.json | 218 ++++ .../crud/client-bulkWrite-delete-options.json | 267 +++++ .../crud/client-bulkWrite-errorResponse.json | 68 ++ .../crud/client-bulkWrite-errors.json | 454 +++++++++ .../client-bulkWrite-mixed-namespaces.json | 314 ++++++ .../crud/client-bulkWrite-options.json | 715 +++++++++++++ .../crud/client-bulkWrite-ordered.json | 290 ++++++ .../crud/client-bulkWrite-results.json | 832 +++++++++++++++ .../crud/client-bulkWrite-update-options.json | 948 ++++++++++++++++++ .../client-bulkWrite-update-pipeline.json | 257 +++++ .../client-bulkWrite-update-validation.json | 216 ++++ .../client-bulkWrite-clientErrors.json | 350 +++++++ .../client-bulkWrite-serverErrors.json | 872 ++++++++++++++++ .../retryable-writes/handshakeError.json | 216 ++++ .../logging/operation-id.json | 187 ++++ .../transactions/client-bulkWrite.json | 592 +++++++++++ .../transactions/mongos-pin-auto.json | 294 ++++++ .../versioned-api/crud-api-version-1.json | 82 +- 18 files changed, 7171 insertions(+), 1 deletion(-) create mode 100644 driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json create mode 100644 driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-validation.json create mode 100644 driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json create mode 100644 driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json create mode 100644 driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json diff --git a/driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json b/driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json new file mode 100644 index 00000000000..1099b6a1e9f --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json @@ -0,0 +1,218 @@ +{ + "description": "unacknowledged-client-bulkWrite", + "schemaVersion": "1.7", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client", + "useMultipleMongoses": false, + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent", + "commandFailedEvent" + ], + "uriOptions": { + "w": 0 + } + } + }, + { + "database": { + "id": "database", + "client": "client", + "databaseName": "command-monitoring-tests" + } + }, + { + "collection": { + "id": "collection", + "database": "database", + "collectionName": "test" + } + } + ], + "initialData": [ + { + "collectionName": "test", + "databaseName": "command-monitoring-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "command-monitoring-tests.test" + }, + "tests": [ + { + "description": "A successful mixed client bulkWrite", + "operations": [ + { + "object": "client", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "command-monitoring-tests.test", + "document": { + "_id": 4, + "x": 44 + } + } + }, + { + "updateOne": { + "namespace": "command-monitoring-tests.test", + "filter": { + "_id": 3 + }, + "update": { + "$set": { + "x": 333 + } + } + } + } + ] + }, + "expectResult": { + "insertedCount": { + "$$unsetOrMatches": 0 + }, + "upsertedCount": { + "$$unsetOrMatches": 0 + }, + "matchedCount": { + "$$unsetOrMatches": 0 + }, + "modifiedCount": { + "$$unsetOrMatches": 0 + }, + "deletedCount": { + "$$unsetOrMatches": 0 + }, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + } + }, + { + "object": "collection", + "name": "find", + "arguments": { + "filter": {} + }, + "expectResult": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 333 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "expectEvents": [ + { + "client": "client", + "ignoreExtraEvents": true, + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 3 + }, + "updateMods": { + "$set": { + "x": 333 + } + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "command-monitoring-tests.test" + } + ] + } + } + }, + { + "commandSucceededEvent": { + "commandName": "bulkWrite", + "reply": { + "ok": 1, + "nInserted": { + "$$exists": false + }, + "nMatched": { + "$$exists": false + }, + "nModified": { + "$$exists": false + }, + "nUpserted": { + "$$exists": false + }, + "nDeleted": { + "$$exists": false + } + } + } + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json new file mode 100644 index 00000000000..5bdf2b124a3 --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json @@ -0,0 +1,267 @@ +{ + "description": "client bulkWrite delete options", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "collation": { + "locale": "simple" + }, + "hint": "_id_" + }, + "tests": [ + { + "description": "client bulk write delete with collation", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "collation": { + "locale": "simple" + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": { + "$gt": 1 + } + }, + "collation": { + "locale": "simple" + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 3, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + }, + "1": { + "deletedCount": 2 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "delete": 0, + "filter": { + "_id": 1 + }, + "collation": { + "locale": "simple" + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": { + "$gt": 1 + } + }, + "collation": { + "locale": "simple" + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [] + } + ] + }, + { + "description": "client bulk write delete with hint", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "hint": "_id_" + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_" + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 3, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + }, + "1": { + "deletedCount": 2 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "delete": 0, + "filter": { + "_id": 1 + }, + "hint": "_id_", + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": { + "$gt": 1 + } + }, + "hint": "_id_", + "multi": true + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json new file mode 100644 index 00000000000..edf2339d8a3 --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json @@ -0,0 +1,68 @@ +{ + "description": "client bulkWrite errorResponse", + "schemaVersion": "1.12", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "useMultipleMongoses": false + } + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite operations support errorResponse assertions", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 8 + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1 + } + } + } + ] + }, + "expectError": { + "errorCode": 8, + "errorResponse": { + "code": 8 + } + } + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json new file mode 100644 index 00000000000..9f17f85331d --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json @@ -0,0 +1,454 @@ +{ + "description": "client bulkWrite errors", + "schemaVersion": "1.21", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ], + "uriOptions": { + "retryWrites": false + }, + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "writeConcernErrorCode": 91, + "writeConcernErrorMessage": "Replication is being shut down", + "undefinedVarCode": 17276 + }, + "tests": [ + { + "description": "an individual operation fails during an ordered bulkWrite", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 1, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + } + } + }, + "writeErrors": { + "1": { + "code": 17276 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "an individual operation fails during an unordered bulkWrite", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true, + "ordered": false + }, + "expectError": { + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 2, + "insertResults": {}, + "updateResults": {}, + "deleteResults": { + "0": { + "deletedCount": 1 + }, + "2": { + "deletedCount": 1 + } + } + }, + "writeErrors": { + "1": { + "code": 17276 + } + } + } + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 2, + "x": 22 + } + ] + } + ] + }, + { + "description": "detailed results are omitted from error when verboseResults is false", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": false + }, + "expectError": { + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 1, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + }, + "writeErrors": { + "1": { + "code": 17276 + } + } + } + } + ] + }, + { + "description": "a top-level failure occurs during a bulkWrite", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 8 + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "x": 1 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "errorCode": 8 + } + } + ] + }, + { + "description": "a bulk write with only errors does not report a partial result", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "expectResult": { + "$$unsetOrMatches": {} + }, + "writeErrors": { + "0": { + "code": 17276 + } + } + } + } + ] + }, + { + "description": "a write concern error occurs during a bulkWrite", + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 10 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 10 + } + }, + "updateResults": {}, + "deleteResults": {} + }, + "writeConcernErrors": [ + { + "code": 91, + "message": "Replication is being shut down" + } + ] + } + } + ] + }, + { + "description": "an empty list of write models is a client-side error", + "operations": [ + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "models": [], + "verboseResults": true + }, + "expectError": { + "isClientError": true + } + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json new file mode 100644 index 00000000000..f90755dc850 --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json @@ -0,0 +1,314 @@ +{ + "description": "client bulkWrite with mixed namespaces", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "db0" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + }, + { + "collection": { + "id": "collection1", + "database": "database0", + "collectionName": "coll1" + } + }, + { + "database": { + "id": "database1", + "client": "client0", + "databaseName": "db1" + } + }, + { + "collection": { + "id": "collection2", + "database": "database1", + "collectionName": "coll2" + } + } + ], + "initialData": [ + { + "databaseName": "db0", + "collectionName": "coll0", + "documents": [] + }, + { + "databaseName": "db0", + "collectionName": "coll1", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + }, + { + "databaseName": "db1", + "collectionName": "coll2", + "documents": [ + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ], + "_yamlAnchors": { + "db0Coll0Namespace": "db0.coll0", + "db0Coll1Namespace": "db0.coll1", + "db1Coll2Namespace": "db1.coll2" + }, + "tests": [ + { + "description": "client bulkWrite with mixed namespaces", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "db0.coll0", + "document": { + "_id": 1 + } + } + }, + { + "insertOne": { + "namespace": "db0.coll0", + "document": { + "_id": 2 + } + } + }, + { + "updateOne": { + "namespace": "db0.coll1", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteOne": { + "namespace": "db1.coll2", + "filter": { + "_id": 3 + } + } + }, + { + "deleteOne": { + "namespace": "db0.coll1", + "filter": { + "_id": 2 + } + } + }, + { + "replaceOne": { + "namespace": "db1.coll2", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 45 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 2, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 2, + "insertResults": { + "0": { + "insertedId": 1 + }, + "1": { + "insertedId": 2 + } + }, + "updateResults": { + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "5": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "3": { + "deletedCount": 1 + }, + "4": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "bulkWrite": 1, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1 + } + }, + { + "insert": 0, + "document": { + "_id": 2 + } + }, + { + "update": 1, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "delete": 2, + "filter": { + "_id": 3 + }, + "multi": false + }, + { + "delete": 1, + "filter": { + "_id": 2 + }, + "multi": false + }, + { + "update": 2, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 45 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "db0.coll0" + }, + { + "ns": "db0.coll1" + }, + { + "ns": "db1.coll2" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "db0", + "collectionName": "coll0", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + }, + { + "databaseName": "db0", + "collectionName": "coll1", + "documents": [ + { + "_id": 1, + "x": 12 + } + ] + }, + { + "databaseName": "db1", + "collectionName": "coll2", + "documents": [ + { + "_id": 4, + "x": 45 + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json new file mode 100644 index 00000000000..a1e6af3bf3b --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json @@ -0,0 +1,715 @@ +{ + "description": "client bulkWrite top-level options", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "client": { + "id": "writeConcernClient", + "uriOptions": { + "w": 1 + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "comment": { + "bulk": "write" + }, + "let": { + "id1": 1, + "id2": 2 + }, + "writeConcern": { + "w": "majority" + } + }, + "tests": [ + { + "description": "client bulkWrite comment", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "comment": { + "bulk": "write" + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "comment": { + "bulk": "write" + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite bypassDocumentValidation", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "bypassDocumentValidation": true, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "bypassDocumentValidation": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite let", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id1" + ] + } + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + } + } + } + ], + "let": { + "id1": 1, + "id2": 2 + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 1, + "modifiedCount": 1, + "deletedCount": 1, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "1": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "let": { + "id1": 1, + "id2": 2 + }, + "ops": [ + { + "update": 0, + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id1" + ] + } + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$expr": { + "$eq": [ + "$_id", + "$$id2" + ] + } + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "x": 12 + } + ] + } + ] + }, + { + "description": "client bulkWrite bypassDocumentValidation: false is sent", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "bypassDocumentValidation": false, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "bypassDocumentValidation": false, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite writeConcern", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "writeConcern": { + "w": "majority" + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "writeConcern": { + "w": "majority" + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite inherits writeConcern from client", + "operations": [ + { + "object": "writeConcernClient", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "writeConcernClient", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "writeConcern": { + "w": 1 + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite writeConcern option overrides client writeConcern", + "operations": [ + { + "object": "writeConcernClient", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 3, + "x": 33 + } + } + } + ], + "writeConcern": { + "w": "majority" + }, + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 3 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "writeConcernClient", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "writeConcern": { + "w": "majority" + }, + "ops": [ + { + "insert": 0, + "document": { + "_id": 3, + "x": 33 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json new file mode 100644 index 00000000000..a55d6619b5e --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json @@ -0,0 +1,290 @@ +{ + "description": "client bulkWrite with ordered option", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with ordered: false", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1, + "x": 11 + } + } + } + ], + "verboseResults": true, + "ordered": false + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 1 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": false, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1, + "x": 11 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "client bulkWrite with ordered: true", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1, + "x": 11 + } + } + } + ], + "verboseResults": true, + "ordered": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 1 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1, + "x": 11 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + }, + { + "description": "client bulkWrite defaults to ordered: true", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 1, + "x": 11 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 1 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 1, + "x": 11 + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json new file mode 100644 index 00000000000..97a9e50b217 --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json @@ -0,0 +1,832 @@ +{ + "description": "client bulkWrite results", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 5, + "x": 55 + }, + { + "_id": 6, + "x": 66 + }, + { + "_id": 7, + "x": 77 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with verboseResults: true returns detailed results", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + }, + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$inc": { + "x": 2 + } + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "upsert": true + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 1, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 3, + "insertResults": { + "0": { + "insertedId": 8 + } + }, + "updateResults": { + "1": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + }, + "3": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedId": 4 + } + }, + "deleteResults": { + "4": { + "deletedCount": 1 + }, + "5": { + "deletedCount": 2 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$inc": { + "x": 2 + } + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 44 + }, + "upsert": true, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 5 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 35 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + }, + { + "description": "client bulkWrite with verboseResults: false omits detailed results", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + }, + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$inc": { + "x": 2 + } + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "upsert": true + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + } + } + } + ], + "verboseResults": false + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 1, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 3, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$inc": { + "x": 2 + } + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 44 + }, + "upsert": true, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 5 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 35 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + }, + { + "description": "client bulkWrite defaults to verboseResults: false", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "crud-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + }, + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$inc": { + "x": 2 + } + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "upsert": true + } + }, + { + "deleteOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + } + } + }, + { + "deleteMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + } + } + } + ] + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 1, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 3, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$inc": { + "x": 2 + } + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 44 + }, + "upsert": true, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 5 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 35 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json new file mode 100644 index 00000000000..93a2774e5fa --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json @@ -0,0 +1,948 @@ +{ + "description": "client bulkWrite update options", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 3 + ] + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0", + "collation": { + "locale": "simple" + }, + "hint": "_id_" + }, + "tests": [ + { + "description": "client bulkWrite update with arrayFilters", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "array.$[i]": 4 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ] + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$set": { + "array.$[i]": 5 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ] + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "1": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$set": { + "array.$[i]": 4 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ], + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$set": { + "array.$[i]": 5 + } + }, + "arrayFilters": [ + { + "i": { + "$gte": 2 + } + } + ], + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 4, + 4 + ] + }, + { + "_id": 2, + "array": [ + 1, + 5, + 5 + ] + }, + { + "_id": 3, + "array": [ + 1, + 5, + 5 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 3 + ] + } + ] + } + ] + }, + { + "description": "client bulkWrite update with collation", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "collation": { + "locale": "simple" + } + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "collation": { + "locale": "simple" + } + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "array": [ + 1, + 2, + 6 + ] + }, + "collation": { + "locale": "simple" + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 4, + "modifiedCount": 4, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "1": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "collation": { + "locale": "simple" + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "collation": { + "locale": "simple" + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "array": [ + 1, + 2, + 6 + ] + }, + "collation": { + "locale": "simple" + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 4 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 6 + ] + } + ] + } + ] + }, + { + "description": "client bulkWrite update with hint", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "hint": "_id_" + } + }, + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "hint": "_id_" + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "array": [ + 1, + 2, + 6 + ] + }, + "hint": "_id_" + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 4, + "modifiedCount": 4, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "1": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "hint": "_id_", + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 5 + ] + } + }, + "hint": "_id_", + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "array": [ + 1, + 2, + 6 + ] + }, + "hint": "_id_", + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 4 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 5 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 6 + ] + } + ] + } + ] + }, + { + "description": "client bulkWrite update with upsert", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 5 + }, + "update": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "upsert": true + } + }, + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 6 + }, + "replacement": { + "array": [ + 1, + 2, + 6 + ] + }, + "upsert": true + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 2, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedId": 5 + }, + "1": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedId": 6 + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 5 + }, + "updateMods": { + "$set": { + "array": [ + 1, + 2, + 4 + ] + } + }, + "upsert": true, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 6 + }, + "updateMods": { + "array": [ + 1, + 2, + 6 + ] + }, + "upsert": true, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 2, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 3, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 4, + "array": [ + 1, + 2, + 3 + ] + }, + { + "_id": 5, + "array": [ + 1, + 2, + 4 + ] + }, + { + "_id": 6, + "array": [ + 1, + 2, + 6 + ] + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json new file mode 100644 index 00000000000..57b6c9c1ba4 --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json @@ -0,0 +1,257 @@ +{ + "description": "client bulkWrite update pipeline", + "schemaVersion": "1.1", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 1 + }, + { + "_id": 2, + "x": 2 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite updateOne with pipeline", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": [ + { + "$addFields": { + "foo": 1 + } + } + ] + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 1, + "modifiedCount": 1, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": [ + { + "$addFields": { + "foo": 1 + } + } + ], + "multi": false + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "x": 1, + "foo": 1 + }, + { + "_id": 2, + "x": 2 + } + ] + } + ] + }, + { + "description": "client bulkWrite updateMany with pipeline", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": {}, + "update": [ + { + "$addFields": { + "foo": 1 + } + } + ] + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 0, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 0, + "insertResults": {}, + "updateResults": { + "0": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": {}, + "updateMods": [ + { + "$addFields": { + "foo": 1 + } + } + ], + "multi": true + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "databaseName": "crud-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "x": 1, + "foo": 1 + }, + { + "_id": 2, + "x": 2, + "foo": 1 + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-validation.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-validation.json new file mode 100644 index 00000000000..617e711338a --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-validation.json @@ -0,0 +1,216 @@ +{ + "description": "client-bulkWrite-update-validation", + "schemaVersion": "1.1", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite replaceOne prohibits atomic modifiers", + "operations": [ + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "models": [ + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "replacement": { + "$set": { + "x": 22 + } + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite updateOne requires atomic modifiers", + "operations": [ + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "x": 22 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + }, + { + "description": "client bulkWrite updateMany requires atomic modifiers", + "operations": [ + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "models": [ + { + "updateMany": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": { + "$gt": 1 + } + }, + "update": { + "x": 44 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json new file mode 100644 index 00000000000..e2c0fb9c0a5 --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json @@ -0,0 +1,350 @@ +{ + "description": "client bulkWrite retryable writes with client errors", + "schemaVersion": "1.21", + "runOnRequirements": [ + { + "minServerVersion": "8.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ], + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "retryable-writes-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with one network error succeeds after retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 4 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "client bulkWrite with two network errors fails after retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "closeConnection": true + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + } + ], + "verboseResults": true + }, + "expectError": { + "isClientError": true, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json new file mode 100644 index 00000000000..4a0b210eb59 --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json @@ -0,0 +1,872 @@ +{ + "description": "client bulkWrite retryable writes", + "schemaVersion": "1.21", + "runOnRequirements": [ + { + "minServerVersion": "8.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ], + "useMultipleMongoses": false + } + }, + { + "client": { + "id": "clientRetryWritesFalse", + "uriOptions": { + "retryWrites": false + }, + "observeEvents": [ + "commandStartedEvent" + ], + "useMultipleMongoses": false + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "retryable-writes-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "retryable-writes-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite with no multi: true operations succeeds after retryable top-level error", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + }, + { + "updateOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "replaceOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 2 + }, + "replacement": { + "x": 222 + } + } + }, + { + "deleteOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 1, + "insertResults": { + "0": { + "insertedId": 4 + } + }, + "updateResults": { + "1": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "3": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "retryable-writes-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 222 + }, + { + "_id": 4, + "x": 44 + } + ] + } + ] + }, + { + "description": "client bulkWrite with multi: true operations fails after retryable top-level error", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ] + }, + "expectError": { + "errorCode": 189, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": true + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite with no multi: true operations succeeds after retryable writeConcernError", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + }, + { + "updateOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "replaceOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 2 + }, + "replacement": { + "x": 222 + } + } + }, + { + "deleteOne": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 2, + "modifiedCount": 2, + "deletedCount": 1, + "insertResults": { + "0": { + "insertedId": 4 + } + }, + "updateResults": { + "1": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + } + }, + "deleteResults": { + "3": { + "deletedCount": 1 + } + } + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "_id": 2 + }, + "updateMods": { + "x": 222 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": false + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ], + "lsid": { + "$$exists": true + }, + "txnNumber": { + "$$exists": true + } + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite with multi: true operations fails after retryable writeConcernError", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "client0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorLabels": [ + "RetryableWriteError" + ], + "writeConcernError": { + "code": 91, + "errmsg": "Replication is being shut down" + } + } + } + } + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "deleteMany": { + "namespace": "retryable-writes-tests.coll0", + "filter": { + "_id": 3 + } + } + } + ] + }, + "expectError": { + "writeConcernErrors": [ + { + "code": 91, + "message": "Replication is being shut down" + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": true + }, + { + "delete": 0, + "filter": { + "_id": 3 + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ] + } + } + } + ] + } + ] + }, + { + "description": "client bulkWrite with retryWrites: false does not retry", + "operations": [ + { + "object": "testRunner", + "name": "failPoint", + "arguments": { + "client": "clientRetryWritesFalse", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 189, + "errorLabels": [ + "RetryableWriteError" + ] + } + } + } + }, + { + "object": "clientRetryWritesFalse", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-tests.coll0", + "document": { + "_id": 4, + "x": 44 + } + } + } + ] + }, + "expectError": { + "errorCode": 189, + "errorLabelsContain": [ + "RetryableWriteError" + ] + } + } + ], + "expectEvents": [ + { + "client": "clientRetryWritesFalse", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 4, + "x": 44 + } + } + ], + "nsInfo": [ + { + "ns": "retryable-writes-tests.coll0" + } + ] + } + } + } + ] + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json b/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json index df37bd72322..3c464637598 100644 --- a/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json +++ b/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json @@ -53,6 +53,222 @@ } ], "tests": [ + { + "description": "client.clientBulkWrite succeeds after retryable handshake network error", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "ping", + "saslContinue" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "clientBulkWrite", + "object": "client", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-handshake-tests.coll", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + } + ] + }, + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "ping": 1 + }, + "databaseName": "retryable-writes-handshake-tests" + } + }, + { + "commandFailedEvent": { + "commandName": "ping" + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite" + } + }, + { + "commandSucceededEvent": { + "commandName": "bulkWrite" + } + } + ] + } + ] + }, + { + "description": "client.clientBulkWrite succeeds after retryable handshake server error (ShutdownInProgress)", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "client", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 2 + }, + "data": { + "failCommands": [ + "ping", + "saslContinue" + ], + "closeConnection": true + } + } + } + }, + { + "name": "runCommand", + "object": "database", + "arguments": { + "commandName": "ping", + "command": { + "ping": 1 + } + }, + "expectError": { + "isError": true + } + }, + { + "name": "clientBulkWrite", + "object": "client", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "retryable-writes-handshake-tests.coll", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "cmap", + "events": [ + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + }, + { + "connectionCheckOutStartedEvent": {} + } + ] + }, + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "command": { + "ping": 1 + }, + "databaseName": "retryable-writes-handshake-tests" + } + }, + { + "commandFailedEvent": { + "commandName": "ping" + } + }, + { + "commandStartedEvent": { + "commandName": "bulkWrite" + } + }, + { + "commandSucceededEvent": { + "commandName": "bulkWrite" + } + } + ] + } + ] + }, { "description": "collection.insertOne succeeds after retryable handshake network error", "operations": [ diff --git a/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json b/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json index 276e4b8d6d9..6cdbcb3f5af 100644 --- a/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json +++ b/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json @@ -47,6 +47,9 @@ } } ], + "_yamlAnchors": { + "namespace": "logging-tests.server-selection" + }, "tests": [ { "description": "Successful bulkWrite operation: log messages have operationIds", @@ -224,6 +227,190 @@ ] } ] + }, + { + "description": "Successful client bulkWrite operation: log messages have operationIds", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 2 + } + }, + { + "name": "clientBulkWrite", + "object": "client", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "logging-tests.server-selection", + "document": { + "x": 1 + } + } + } + ] + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "serverSelection", + "data": { + "message": "Server selection started", + "operationId": { + "$$type": [ + "int", + "long" + ] + }, + "operation": "bulkWrite" + } + }, + { + "level": "debug", + "component": "serverSelection", + "data": { + "message": "Server selection succeeded", + "operationId": { + "$$type": [ + "int", + "long" + ] + }, + "operation": "bulkWrite" + } + } + ] + } + ] + }, + { + "description": "Failed client bulkWrite operation: log messages have operationIds", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "failPoint", + "object": "testRunner", + "arguments": { + "client": "failPointClient", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": "alwaysOn", + "data": { + "failCommands": [ + "hello", + "ismaster" + ], + "appName": "loggingClient", + "closeConnection": true + } + } + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "serverDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + "count": 1 + } + }, + { + "name": "bulkWrite", + "object": "client", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "logging-tests.server-selection", + "document": { + "x": 1 + } + } + } + ] + }, + "expectError": { + "isClientError": true + } + } + ], + "expectLogMessages": [ + { + "client": "client", + "messages": [ + { + "level": "debug", + "component": "serverSelection", + "data": { + "message": "Server selection started", + "operationId": { + "$$type": [ + "int", + "long" + ] + }, + "operation": "bulkWrite" + } + }, + { + "level": "info", + "component": "serverSelection", + "data": { + "message": "Waiting for suitable server to become available", + "operationId": { + "$$type": [ + "int", + "long" + ] + }, + "operation": "bulkWrite" + } + }, + { + "level": "debug", + "component": "serverSelection", + "data": { + "message": "Server selection failed", + "operationId": { + "$$type": [ + "int", + "long" + ] + }, + "operation": "bulkWrite" + } + } + ] + } + ] } ] } diff --git a/driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json b/driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json new file mode 100644 index 00000000000..f8f1d97169d --- /dev/null +++ b/driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json @@ -0,0 +1,592 @@ +{ + "description": "client bulkWrite transactions", + "schemaVersion": "1.3", + "runOnRequirements": [ + { + "minServerVersion": "8.0", + "topologies": [ + "replicaset", + "sharded", + "load-balanced" + ] + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "transaction-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + }, + { + "session": { + "id": "session0", + "client": "client0" + } + }, + { + "client": { + "id": "client_with_wmajority", + "uriOptions": { + "w": "majority" + }, + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "session": { + "id": "session_with_wmajority", + "client": "client_with_wmajority" + } + } + ], + "_yamlAnchors": { + "namespace": "transaction-tests.coll0" + }, + "initialData": [ + { + "databaseName": "transaction-tests", + "collectionName": "coll0", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 5, + "x": 55 + }, + { + "_id": 6, + "x": 66 + }, + { + "_id": 7, + "x": 77 + } + ] + } + ], + "tests": [ + { + "description": "client bulkWrite in a transaction", + "operations": [ + { + "object": "session0", + "name": "startTransaction" + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "session": "session0", + "models": [ + { + "insertOne": { + "namespace": "transaction-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + }, + { + "updateOne": { + "namespace": "transaction-tests.coll0", + "filter": { + "_id": 1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + }, + { + "updateMany": { + "namespace": "transaction-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "update": { + "$inc": { + "x": 2 + } + } + } + }, + { + "replaceOne": { + "namespace": "transaction-tests.coll0", + "filter": { + "_id": 4 + }, + "replacement": { + "x": 44 + }, + "upsert": true + } + }, + { + "deleteOne": { + "namespace": "transaction-tests.coll0", + "filter": { + "_id": 5 + } + } + }, + { + "deleteMany": { + "namespace": "transaction-tests.coll0", + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 1, + "matchedCount": 3, + "modifiedCount": 3, + "deletedCount": 3, + "insertResults": { + "0": { + "insertedId": 8 + } + }, + "updateResults": { + "1": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedId": { + "$$exists": false + } + }, + "2": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedId": { + "$$exists": false + } + }, + "3": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedId": 4 + } + }, + "deleteResults": { + "4": { + "deletedCount": 1 + }, + "5": { + "deletedCount": 2 + } + } + } + }, + { + "object": "session0", + "name": "commitTransaction" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "writeConcern": { + "$$exists": false + }, + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + }, + { + "update": 0, + "filter": { + "_id": 1 + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "multi": false + }, + { + "update": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 1 + } + }, + { + "_id": { + "$lte": 3 + } + } + ] + }, + "updateMods": { + "$inc": { + "x": 2 + } + }, + "multi": true + }, + { + "update": 0, + "filter": { + "_id": 4 + }, + "updateMods": { + "x": 44 + }, + "upsert": true, + "multi": false + }, + { + "delete": 0, + "filter": { + "_id": 5 + }, + "multi": false + }, + { + "delete": 0, + "filter": { + "$and": [ + { + "_id": { + "$gt": 5 + } + }, + { + "_id": { + "$lte": 7 + } + } + ] + }, + "multi": true + } + ], + "nsInfo": [ + { + "ns": "transaction-tests.coll0" + } + ] + } + } + }, + { + "commandStartedEvent": { + "commandName": "commitTransaction", + "databaseName": "admin", + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session0" + }, + "txnNumber": 1, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "$$exists": false + } + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1, + "x": 12 + }, + { + "_id": 2, + "x": 24 + }, + { + "_id": 3, + "x": 35 + }, + { + "_id": 4, + "x": 44 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + }, + { + "description": "client writeConcern ignored for client bulkWrite in transaction", + "operations": [ + { + "object": "session_with_wmajority", + "name": "startTransaction", + "arguments": { + "writeConcern": { + "w": 1 + } + } + }, + { + "object": "client_with_wmajority", + "name": "clientBulkWrite", + "arguments": { + "session": "session_with_wmajority", + "models": [ + { + "insertOne": { + "namespace": "transaction-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "$$unsetOrMatches": {} + }, + "updateResults": { + "$$unsetOrMatches": {} + }, + "deleteResults": { + "$$unsetOrMatches": {} + } + } + }, + { + "object": "session_with_wmajority", + "name": "commitTransaction" + } + ], + "expectEvents": [ + { + "client": "client_with_wmajority", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "lsid": { + "$$sessionLsid": "session_with_wmajority" + }, + "txnNumber": 1, + "startTransaction": true, + "autocommit": false, + "writeConcern": { + "$$exists": false + }, + "bulkWrite": 1, + "errorsOnly": true, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 8, + "x": 88 + } + } + ], + "nsInfo": [ + { + "ns": "transaction-tests.coll0" + } + ] + } + } + }, + { + "commandStartedEvent": { + "command": { + "commitTransaction": 1, + "lsid": { + "$$sessionLsid": "session_with_wmajority" + }, + "txnNumber": { + "$numberLong": "1" + }, + "startTransaction": { + "$$exists": false + }, + "autocommit": false, + "writeConcern": { + "w": 1 + } + }, + "commandName": "commitTransaction", + "databaseName": "admin" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + }, + { + "_id": 5, + "x": 55 + }, + { + "_id": 6, + "x": 66 + }, + { + "_id": 7, + "x": 77 + }, + { + "_id": 8, + "x": 88 + } + ] + } + ] + }, + { + "description": "client bulkWrite with writeConcern in a transaction causes a transaction error", + "operations": [ + { + "object": "session0", + "name": "startTransaction" + }, + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "session": "session0", + "writeConcern": { + "w": 1 + }, + "models": [ + { + "insertOne": { + "namespace": "transaction-tests.coll0", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + }, + "expectError": { + "isClientError": true, + "errorContains": "Cannot set write concern after starting a transaction" + } + } + ] + } + ] +} diff --git a/driver-core/src/test/resources/unified-test-format/transactions/mongos-pin-auto.json b/driver-core/src/test/resources/unified-test-format/transactions/mongos-pin-auto.json index 93eac8bb773..27db5204011 100644 --- a/driver-core/src/test/resources/unified-test-format/transactions/mongos-pin-auto.json +++ b/driver-core/src/test/resources/unified-test-format/transactions/mongos-pin-auto.json @@ -2004,6 +2004,104 @@ } ] }, + { + "description": "remain pinned after non-transient Interrupted error on clientBulkWrite bulkWrite", + "operations": [ + { + "object": "session0", + "name": "startTransaction" + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "session": "session0", + "document": { + "_id": 3 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + }, + { + "name": "targetedFailPoint", + "object": "testRunner", + "arguments": { + "session": "session0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 11601 + } + } + } + }, + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "session": "session0", + "models": [ + { + "insertOne": { + "namespace": "database0.collection0", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + }, + "expectError": { + "errorLabelsOmit": [ + "TransientTransactionError" + ] + } + }, + { + "object": "testRunner", + "name": "assertSessionPinned", + "arguments": { + "session": "session0" + } + }, + { + "object": "session0", + "name": "abortTransaction" + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ] + }, { "description": "unpin after transient connection error on insertOne insert", "operations": [ @@ -5175,6 +5273,202 @@ ] } ] + }, + { + "description": "unpin after transient connection error on clientBulkWrite bulkWrite", + "operations": [ + { + "object": "session0", + "name": "startTransaction" + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "session": "session0", + "document": { + "_id": 3 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + }, + { + "name": "targetedFailPoint", + "object": "testRunner", + "arguments": { + "session": "session0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "closeConnection": true + } + } + } + }, + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "session": "session0", + "models": [ + { + "insertOne": { + "namespace": "database0.collection0", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + }, + "expectError": { + "errorLabelsContain": [ + "TransientTransactionError" + ] + } + }, + { + "object": "testRunner", + "name": "assertSessionUnpinned", + "arguments": { + "session": "session0" + } + }, + { + "object": "session0", + "name": "abortTransaction" + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ] + }, + { + "description": "unpin after transient ShutdownInProgress error on clientBulkWrite bulkWrite", + "operations": [ + { + "object": "session0", + "name": "startTransaction" + }, + { + "object": "collection0", + "name": "insertOne", + "arguments": { + "session": "session0", + "document": { + "_id": 3 + } + }, + "expectResult": { + "$$unsetOrMatches": { + "insertedId": { + "$$unsetOrMatches": 3 + } + } + } + }, + { + "name": "targetedFailPoint", + "object": "testRunner", + "arguments": { + "session": "session0", + "failPoint": { + "configureFailPoint": "failCommand", + "mode": { + "times": 1 + }, + "data": { + "failCommands": [ + "bulkWrite" + ], + "errorCode": 91 + } + } + } + }, + { + "name": "clientBulkWrite", + "object": "client0", + "arguments": { + "session": "session0", + "models": [ + { + "insertOne": { + "namespace": "database0.collection0", + "document": { + "_id": 8, + "x": 88 + } + } + } + ] + }, + "expectError": { + "errorLabelsContain": [ + "TransientTransactionError" + ] + } + }, + { + "object": "testRunner", + "name": "assertSessionUnpinned", + "arguments": { + "session": "session0" + } + }, + { + "object": "session0", + "name": "abortTransaction" + } + ], + "outcome": [ + { + "collectionName": "test", + "databaseName": "transaction-tests", + "documents": [ + { + "_id": 1 + }, + { + "_id": 2 + } + ] + } + ], + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ] } ] } diff --git a/driver-core/src/test/resources/versioned-api/crud-api-version-1.json b/driver-core/src/test/resources/versioned-api/crud-api-version-1.json index a387d0587e0..fe668620f82 100644 --- a/driver-core/src/test/resources/versioned-api/crud-api-version-1.json +++ b/driver-core/src/test/resources/versioned-api/crud-api-version-1.json @@ -50,7 +50,8 @@ }, "apiDeprecationErrors": true } - ] + ], + "namespace": "versioned-api-tests.test" }, "initialData": [ { @@ -426,6 +427,85 @@ } ] }, + { + "description": "client bulkWrite appends declared API version", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "clientBulkWrite", + "object": "client", + "arguments": { + "models": [ + { + "insertOne": { + "namespace": "versioned-api-tests.test", + "document": { + "_id": 6, + "x": 6 + } + } + } + ], + "verboseResults": true + }, + "expectResult": { + "insertedCount": 1, + "upsertedCount": 0, + "matchedCount": 0, + "modifiedCount": 0, + "deletedCount": 0, + "insertResults": { + "0": { + "insertedId": 6 + } + }, + "updateResults": {}, + "deleteResults": {} + } + } + ], + "expectEvents": [ + { + "client": "client", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "errorsOnly": false, + "ordered": true, + "ops": [ + { + "insert": 0, + "document": { + "_id": 6, + "x": 6 + } + } + ], + "nsInfo": [ + { + "ns": "versioned-api-tests.test" + } + ], + "apiVersion": "1", + "apiStrict": { + "$$unsetOrMatches": false + }, + "apiDeprecationErrors": true + } + } + } + ] + } + ] + }, { "description": "countDocuments appends declared API version", "operations": [ From 16f100bf8902873e094630171b9b675833045af6 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 15 Aug 2024 17:14:06 -0600 Subject: [PATCH 12/59] Implement required test runner changes JAVA-5528 --- .../mongodb/client/unified/ErrorMatcher.java | 67 ++++- .../client/unified/UnifiedCrudHelper.java | 238 ++++++++++++++++++ .../mongodb/client/unified/UnifiedTest.java | 5 +- .../unified/UnifiedTransactionsTest.java | 2 + 4 files changed, 304 insertions(+), 8 deletions(-) diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java b/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java index 75d264487f8..b8692c53a1c 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java @@ -16,6 +16,7 @@ package com.mongodb.client.unified; +import com.mongodb.ClientBulkWriteException; import com.mongodb.MongoBulkWriteException; import com.mongodb.MongoClientException; import com.mongodb.MongoCommandException; @@ -27,23 +28,33 @@ import com.mongodb.MongoSocketException; import com.mongodb.MongoWriteConcernException; import com.mongodb.MongoWriteException; +import com.mongodb.WriteError; +import com.mongodb.bulk.WriteConcernError; import org.bson.BsonDocument; +import org.bson.BsonInt32; +import org.bson.BsonString; import org.bson.BsonValue; import java.util.HashSet; +import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; +import static java.lang.Long.parseLong; import static java.util.Arrays.asList; +import static java.util.stream.Collectors.toList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.spockframework.util.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; final class ErrorMatcher { private static final Set EXPECTED_ERROR_FIELDS = new HashSet<>( asList("isError", "expectError", "isClientError", "errorCode", "errorCodeName", "errorContains", "errorResponse", - "isClientError", "isTimeoutError", "errorLabelsOmit", "errorLabelsContain", "expectResult")); + "isClientError", "isTimeoutError", "errorLabelsOmit", "errorLabelsContain", + "writeErrors", "writeConcernErrors", "expectResult")); private final AssertionContext context; private final ValueMatcher valueMatcher; @@ -134,13 +145,55 @@ void assertErrorsMatch(final BsonDocument expectedError, final Exception e) { mongoException.hasErrorLabel(cur.asString().getValue())); } } + if (expectedError.containsKey("writeErrors")) { + assertTrue(context.getMessage("Exception must be of type ClientBulkWriteException when checking for write errors"), + e instanceof ClientBulkWriteException); + BsonDocument writeErrors = expectedError.getDocument("writeErrors"); + ClientBulkWriteException actualException = (ClientBulkWriteException) e; + Map actualWriteErrors = actualException.getWriteErrors(); + assertEquals("The number of write errors must match", writeErrors.size(), actualWriteErrors.size()); + writeErrors.forEach((index, writeError) -> { + WriteError actualWriteError = actualWriteErrors.get(parseLong(index)); + assertNotNull("Expected a write error with index " + index, actualWriteError); + valueMatcher.assertValuesMatch(writeError, toMatchableValue(actualWriteError)); + }); + } + if (expectedError.containsKey("writeConcernErrors")) { + assertTrue(context.getMessage("Exception must be of type ClientBulkWriteException when checking for write errors"), + e instanceof ClientBulkWriteException); + List writeConcernErrors = expectedError.getArray("writeConcernErrors").stream() + .map(BsonValue::asDocument).collect(toList()); + ClientBulkWriteException actualException = (ClientBulkWriteException) e; + List actualWriteConcernErrors = actualException.getWriteConcernErrors(); + assertEquals("The number of write concern errors must match", writeConcernErrors.size(), actualWriteConcernErrors.size()); + for (int index = 0; index < writeConcernErrors.size(); index++) { + BsonDocument writeConcernError = writeConcernErrors.get(index); + WriteConcernError actualWriteConcernError = actualWriteConcernErrors.get(index); + valueMatcher.assertValuesMatch(writeConcernError, toMatchableValue(actualWriteConcernError)); + } + } if (expectedError.containsKey("expectResult")) { - // Neither MongoBulkWriteException nor MongoSocketException includes information about the successful writes, so this - // is the only check that can currently be done - assertTrue(context.getMessage("Exception must be of type MongoBulkWriteException or MongoSocketException " - + "when checking for results, but actual type is " + e.getClass().getSimpleName()), - e instanceof MongoBulkWriteException || e instanceof MongoSocketException); + assertTrue(context.getMessage("Exception must be of type" + + " MongoBulkWriteException, or MongoSocketException, or ClientBulkWriteException" + + " when checking for results, but actual type is " + e.getClass().getSimpleName()), + e instanceof MongoBulkWriteException || e instanceof ClientBulkWriteException || e instanceof MongoSocketException); + // neither `MongoBulkWriteException` nor `MongoSocketException` includes information about the successful individual operations + if (e instanceof ClientBulkWriteException) { + BsonDocument actualPartialResult = ((ClientBulkWriteException) e).getPartialResult() + .map(UnifiedCrudHelper::toMatchableValue) + .orElse(new BsonDocument()); + valueMatcher.assertValuesMatch(expectedError.getDocument("expectResult"), actualPartialResult); + } } context.pop(); } + + private static BsonDocument toMatchableValue(final WriteError writeError) { + return new BsonDocument("code", new BsonInt32(writeError.getCode())); + } + + private static BsonDocument toMatchableValue(final WriteConcernError writeConcernError) { + return new BsonDocument("code", new BsonInt32(writeConcernError.getCode())) + .append("message", new BsonString(writeConcernError.getMessage())); + } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index 041f016510f..c63075f315b 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -75,6 +75,12 @@ import com.mongodb.client.model.UpdateOneModel; import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.model.WriteModel; +import com.mongodb.client.model.bulk.ClientBulkWriteOptions; +import com.mongodb.client.model.bulk.ClientDeleteOptions; +import com.mongodb.client.model.bulk.ClientReplaceOptions; +import com.mongodb.client.model.bulk.ClientUpdateOptions; +import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocumentBeforeChange; @@ -82,7 +88,10 @@ import com.mongodb.client.result.InsertManyResult; import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.UpdateResult; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.result.bulk.ClientUpdateResult; import com.mongodb.lang.NonNull; +import com.mongodb.lang.Nullable; import org.bson.BsonArray; import org.bson.BsonDocument; import org.bson.BsonDocumentWriter; @@ -101,15 +110,23 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; +import static com.mongodb.client.model.bulk.ClientBulkWriteOptions.clientBulkWriteOptions; +import static com.mongodb.client.model.bulk.ClientDeleteOptions.clientDeleteOptions; +import static com.mongodb.client.model.bulk.ClientReplaceOptions.clientReplaceOptions; +import static com.mongodb.client.model.bulk.ClientUpdateOptions.clientUpdateOptions; +import static java.lang.String.format; import static java.util.Arrays.asList; +import static java.util.Collections.singleton; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; @@ -215,6 +232,7 @@ private OperationResult resultOf(final Supplier operationResult) { } } + @Nullable private ClientSession getSession(final BsonDocument arguments) { if (arguments.containsKey("session")) { return entities.getSession(arguments.getString("session").asString().getValue()); @@ -1760,6 +1778,226 @@ public OperationResult createChangeStreamCursor(final BsonDocument operation) { }); } + public OperationResult clientBulkWrite(final BsonDocument operation) { + Set unexpectedOperationKeys = singleton("saveResultAsEntity"); + if (operation.keySet().stream().anyMatch(unexpectedOperationKeys::contains)) { + throw new UnsupportedOperationException("Unexpected field in operation. One of " + unexpectedOperationKeys); + } + String clientId = operation.getString("object").getValue(); + MongoCluster cluster = entities.getClient(clientId); + BsonDocument arguments = operation.getDocument("arguments"); + ClientSession session = getSession(arguments); + List models = arguments.getArray("models").stream() + .map(BsonValue::asDocument) + .map(UnifiedCrudHelper::toClientWriteModelWithNamespace) + .collect(toList()); + ClientBulkWriteOptions options = clientBulkWriteOptions(); + for (Map.Entry entry : arguments.entrySet()) { + String key = entry.getKey(); + BsonValue argument = entry.getValue(); + switch (key) { + case "models": + case "session": + break; + case "writeConcern": + cluster = cluster.withWriteConcern(asWriteConcern(argument.asDocument())); + break; + case "ordered": + options.ordered(argument.asBoolean().getValue()); + break; + case "bypassDocumentValidation": + options.bypassDocumentValidation(argument.asBoolean().getValue()); + break; + case "let": + options.let(argument.asDocument()); + break; + case "comment": + options.comment(argument); + break; + case "verboseResults": + options.verboseResults(argument.asBoolean().getValue()); + break; + default: + throw new UnsupportedOperationException(format("Unsupported argument: key=%s, argument=%s", key, argument)); + } + } + MongoCluster clusterWithWriteConcern = cluster; + return resultOf(() -> { + if (session == null) { + return toMatchableValue(clusterWithWriteConcern.bulkWrite(models, options)); + } else { + return toMatchableValue(clusterWithWriteConcern.bulkWrite(session, models, options)); + } + }); + } + + private static ClientWriteModelWithNamespace toClientWriteModelWithNamespace(final BsonDocument model) { + String modelType = model.getFirstKey(); + BsonDocument arguments = model.getDocument(modelType); + MongoNamespace namespace = new MongoNamespace(arguments.getString("namespace").getValue()); + switch (modelType) { + case "insertOne": + Set expectedArguments = new HashSet<>(asList("namespace", "document")); + if (!expectedArguments.containsAll(arguments.keySet())) { + throw new UnsupportedOperationException("Unsupported argument, one of: " + arguments.keySet()); + } + return ClientWriteModel.insertOne( + arguments.getDocument("document")).withNamespace(namespace); + case "replaceOne": + return ClientWriteModel.replaceOne( + arguments.getDocument("filter"), + arguments.getDocument("replacement"), + getClientReplaceOptions(arguments)).withNamespace(namespace); + case "updateOne": + return arguments.isDocument("update") + ? ClientWriteModel.updateOne( + arguments.getDocument("filter"), + arguments.getDocument("update"), + getClientUpdateOptions(arguments)).withNamespace(namespace) + : ClientWriteModel.updateOne( + arguments.getDocument("filter"), + arguments.getArray("update").stream().map(BsonValue::asDocument).collect(toList()), + getClientUpdateOptions(arguments)).withNamespace(namespace); + case "updateMany": + return arguments.isDocument("update") + ? ClientWriteModel.updateMany( + arguments.getDocument("filter"), + arguments.getDocument("update"), + getClientUpdateOptions(arguments)).withNamespace(namespace) + : ClientWriteModel.updateMany( + arguments.getDocument("filter"), + arguments.getArray("update").stream().map(BsonValue::asDocument).collect(toList()), + getClientUpdateOptions(arguments)).withNamespace(namespace); + case "deleteOne": + return ClientWriteModel.deleteOne( + arguments.getDocument("filter"), + getClientDeleteOptions(arguments)).withNamespace(namespace); + case "deleteMany": + return ClientWriteModel.deleteMany( + arguments.getDocument("filter"), + getClientDeleteOptions(arguments)).withNamespace(namespace); + default: + throw new UnsupportedOperationException("Unsupported client write model type: " + modelType); + } + } + + private static ClientReplaceOptions getClientReplaceOptions(final BsonDocument arguments) { + ClientReplaceOptions options = clientReplaceOptions(); + arguments.forEach((key, argument) -> { + switch (key) { + case "namespace": + case "filter": + case "replacement": + break; + case "collation": + options.collation(asCollation(argument.asDocument())); + break; + case "hint": + if (argument.isDocument()) { + options.hint(argument.asDocument()); + } else { + options.hintString(argument.asString().getValue()); + } + break; + case "upsert": + options.upsert(argument.asBoolean().getValue()); + break; + default: + throw new UnsupportedOperationException(format("Unsupported argument: key=%s, argument=%s", key, argument)); + } + }); + return options; + } + + private static ClientUpdateOptions getClientUpdateOptions(final BsonDocument arguments) { + ClientUpdateOptions options = clientUpdateOptions(); + arguments.forEach((key, argument) -> { + switch (key) { + case "namespace": + case "filter": + case "update": + break; + case "arrayFilters": + options.arrayFilters(argument.asArray().stream().map(BsonValue::asDocument).collect(toList())); + break; + case "collation": + options.collation(asCollation(argument.asDocument())); + break; + case "hint": + if (argument.isDocument()) { + options.hint(argument.asDocument()); + } else { + options.hintString(argument.asString().getValue()); + } + break; + case "upsert": + options.upsert(argument.asBoolean().getValue()); + break; + default: + throw new UnsupportedOperationException(format("Unsupported argument: key=%s, argument=%s", key, argument)); + } + }); + return options; + } + + private static ClientDeleteOptions getClientDeleteOptions(final BsonDocument arguments) { + ClientDeleteOptions options = clientDeleteOptions(); + arguments.forEach((key, argument) -> { + switch (key) { + case "namespace": + case "filter": + break; + case "collation": + options.collation(asCollation(argument.asDocument())); + break; + case "hint": + if (argument.isDocument()) { + options.hint(argument.asDocument()); + } else { + options.hintString(argument.asString().getValue()); + } + break; + default: + throw new UnsupportedOperationException(format("Unsupported argument: key=%s, argument=%s", key, argument)); + } + }); + return options; + } + + static BsonDocument toMatchableValue(final ClientBulkWriteResult result) { + BsonDocument expected = new BsonDocument(); + if (result.isAcknowledged()) { + expected.append("insertedCount", new BsonInt64(result.getInsertedCount())) + .append("upsertedCount", new BsonInt64(result.getUpsertedCount())) + .append("matchedCount", new BsonInt64(result.getMatchedCount())) + .append("modifiedCount", new BsonInt64(result.getModifiedCount())) + .append("deletedCount", new BsonInt64(result.getDeletedCount())); + if (result.hasVerboseResults()) { + expected.append("insertResults", new BsonDocument(result.getInsertResults().entrySet().stream() + .map(entry -> new BsonElement( + entry.getKey().toString(), + new BsonDocument("insertedId", entry.getValue().getInsertedId()))) + .collect(toList()))) + .append("updateResults", new BsonDocument(result.getUpdateResults().entrySet().stream() + .map(entry -> { + ClientUpdateResult updateResult = entry.getValue(); + BsonDocument updateResultDocument = new BsonDocument( + "matchedCount", new BsonInt64(updateResult.getMatchedCount())) + .append("modifiedCount", new BsonInt64(updateResult.getModifiedCount())); + updateResult.getUpsertedId().ifPresent(upsertedId -> updateResultDocument.append("upsertedId", upsertedId)); + return new BsonElement(entry.getKey().toString(), updateResultDocument); + }) + .collect(toList()))) + .append("deleteResults", new BsonDocument(result.getDeleteResults().entrySet().stream() + .map(entry -> new BsonElement( + entry.getKey().toString(), + new BsonDocument("deletedCount", new BsonInt64(entry.getValue().getDeletedCount())))) + .collect(toList()))); + } + } + return expected; + } + public OperationResult executeIterateUntilDocumentOrError(final BsonDocument operation) { String id = operation.getString("object").getValue(); MongoCursor cursor = entities.getCursor(id); diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java index 58ad07034ec..642999547e9 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java @@ -229,7 +229,8 @@ public void setUp( || schemaVersion.equals("1.16") || schemaVersion.equals("1.17") || schemaVersion.equals("1.18") - || schemaVersion.equals("1.19"), + || schemaVersion.equals("1.19") + || schemaVersion.equals("1.21"), String.format("Unsupported schema version %s", schemaVersion)); if (runOnRequirements != null) { assumeTrue(runOnRequirementsMet(runOnRequirements, getMongoClientSettings(), getServerVersion()), @@ -538,6 +539,8 @@ private OperationResult executeOperation(final UnifiedTestContext context, final return crudHelper.createFindCursor(operation); case "createChangeStream": return crudHelper.createChangeStreamCursor(operation); + case "clientBulkWrite": + return crudHelper.clientBulkWrite(operation); case "close": return crudHelper.close(operation); case "iterateUntilDocumentOrError": diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java index 5acf74cd972..216fdf099d3 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTransactionsTest.java @@ -36,6 +36,8 @@ protected void skips(final String fileDescription, final String testDescription) assumeFalse(fileDescription.equals("read-concern") && testDescription.equals("distinct ignores collection readConcern")); assumeFalse(fileDescription.equals("reads") && testDescription.equals("distinct")); } + // `MongoCluster.getWriteConcern`/`MongoCollection.getWriteConcern` are silently ignored in a transaction + assumeFalse(testDescription.equals("client bulkWrite with writeConcern in a transaction causes a transaction error")); } private static Collection data() throws URISyntaxException, IOException { From 9f8ce2c0e2c736ccf3cc25c9c692f959be9e1538 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 12:41:35 -0600 Subject: [PATCH 13/59] Improve how `indexedNamespaces` are computed JAVA-5528 --- .../internal/operation/ClientBulkWriteOperation.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index 69cdba35233..db558351e2e 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -359,10 +359,8 @@ public void encode(final BsonWriter writer, final String commandName, final Enco commandIsRetryable = false; logWriteModelDoesNotSupportRetries(); } - MongoNamespace namespace = modelWithNamespace.getNamespace(); - int namespaceIndexInBatch = indexedNamespaces.size(); - Integer existingNamespaceIndex = indexedNamespaces.putIfAbsent(namespace, namespaceIndexInBatch); - namespaceIndexInBatch = existingNamespaceIndex == null ? namespaceIndexInBatch : existingNamespaceIndex; + int namespaceIndexInBatch = indexedNamespaces.computeIfAbsent( + modelWithNamespace.getNamespace(), k -> indexedNamespaces.size()); batchEncoder.encodeWriteModel(writer, model, modelIndexInBatch, namespaceIndexInBatch); } writer.writeEndArray(); From fdb90d2a5fdb799fa69c1d6f0414269cedf1563a Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 13:33:40 -0600 Subject: [PATCH 14/59] Remove `throws` declarations from the API JAVA-5527 --- .../result/bulk/ClientBulkWriteResult.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java index b30aaec4365..e6207826889 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java @@ -52,7 +52,7 @@ public interface ClientBulkWriteResult { * @return Whether there are verbose results. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - boolean hasVerboseResults() throws UnsupportedOperationException; + boolean hasVerboseResults(); /** * The number of documents that were inserted across all insert operations. @@ -60,7 +60,7 @@ public interface ClientBulkWriteResult { * @return The number of documents that were inserted. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - long getInsertedCount() throws UnsupportedOperationException; + long getInsertedCount(); /** * The number of documents that were upserted across all update and replace operations. @@ -68,7 +68,7 @@ public interface ClientBulkWriteResult { * @return The number of documents that were upserted. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - long getUpsertedCount() throws UnsupportedOperationException; + long getUpsertedCount(); /** * The number of documents that matched the filters across all operations with filters. @@ -76,7 +76,7 @@ public interface ClientBulkWriteResult { * @return The number of documents that were matched. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - long getMatchedCount() throws UnsupportedOperationException; + long getMatchedCount(); /** * The number of documents that were modified across all update and replace operations. @@ -84,7 +84,7 @@ public interface ClientBulkWriteResult { * @return The number of documents that were modified. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - long getModifiedCount() throws UnsupportedOperationException; + long getModifiedCount(); /** * The number of documents that were deleted across all delete operations. @@ -92,7 +92,7 @@ public interface ClientBulkWriteResult { * @return The number of documents that were deleted. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - long getDeletedCount() throws UnsupportedOperationException; + long getDeletedCount(); /** * The indexed {@link ClientInsertOneResult}s. @@ -106,7 +106,7 @@ public interface ClientBulkWriteResult { * or does not have {@linkplain #hasVerboseResults() verbose results}. * @see ClientBulkWriteException#getWriteErrors() */ - Map getInsertResults() throws UnsupportedOperationException; + Map getInsertResults(); /** * The indexed {@link ClientUpdateResult}s. @@ -120,7 +120,7 @@ public interface ClientBulkWriteResult { * or does not have {@linkplain #hasVerboseResults() verbose results}. * @see ClientBulkWriteException#getWriteErrors() */ - Map getUpdateResults() throws UnsupportedOperationException; + Map getUpdateResults(); /** * The indexed {@link ClientDeleteResult}s. @@ -134,5 +134,5 @@ public interface ClientBulkWriteResult { * or does not have {@linkplain #hasVerboseResults() verbose results}. * @see ClientBulkWriteException#getWriteErrors() */ - Map getDeleteResults() throws UnsupportedOperationException; + Map getDeleteResults(); } From 39386fef740c8d45e75d6a8d80e61f7c8dffad9a Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 13:41:28 -0600 Subject: [PATCH 15/59] Make wording on `ClientWriteModel` methods consistent with that on `ClientWriteModel` subtypes JAVA-5527 --- .../client/model/bulk/ClientWriteModel.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java index 2bab92bffd8..0dc6e57499c 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java @@ -53,7 +53,7 @@ static ClientInsertOneModel insertOne(final TDocument document) { } /** - * Creates a model for updating at most one document that matches the {@code filter}. + * Creates a model for updating at most one document matching the {@code filter}. * This method is functionally equivalent to {@link #updateOne(Bson, Bson, ClientUpdateOptions)} * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. * @@ -70,7 +70,7 @@ static ClientUpdateOneModel updateOne(final Bson filter, final Bson update) { } /** - * Creates a model for updating at most one document that matches the {@code filter}. + * Creates a model for updating at most one document matching the {@code filter}. * * @param filter The filter. * @param update The update. @@ -87,7 +87,7 @@ static ClientUpdateOneModel updateOne(final Bson filter, final Bson update, fina } /** - * Creates a model for updating at most one document that matches the {@code filter}. + * Creates a model for updating at most one document matching the {@code filter}. * This method is functionally equivalent to {@link #updateOne(Bson, Iterable, ClientUpdateOptions)} * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. * @@ -104,7 +104,7 @@ static ClientUpdateOneModel updateOne(final Bson filter, final Iterable ClientReplaceOneModel replaceOne(final Bson filter, final TDo } /** - * Creates a model for replacing at most one document that matches the {@code filter}. + * Creates a model for replacing at most one document matching the {@code filter}. * * @param filter The filter. * @param replacement The replacement. @@ -225,7 +225,7 @@ static ClientReplaceOneModel replaceOne(final Bson filter, final TDo } /** - * Creates a model for removing at most one document that match the {@code filter}. + * Creates a model for removing at most one document matching the {@code filter}. * This method is functionally equivalent to {@link #deleteOne(Bson, ClientDeleteOptions)} * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. * @@ -239,7 +239,7 @@ static ClientDeleteOneModel deleteOne(final Bson filter) { } /** - * Creates a model for removing at most one document that match the {@code filter}. + * Creates a model for removing at most one document matching the {@code filter}. * * @param filter The filter. * @param options The options. @@ -253,7 +253,7 @@ static ClientDeleteOneModel deleteOne(final Bson filter, final ClientDeleteOptio } /** - * Creates a model for removing all documents that match the {@code filter}. + * Creates a model for removing all documents matching the {@code filter}. * This method is functionally equivalent to {@link #deleteMany(Bson, ClientDeleteOptions)} * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. * @@ -267,7 +267,7 @@ static ClientDeleteManyModel deleteMany(final Bson filter) { } /** - * Creates a model for removing all documents that match the {@code filter}. + * Creates a model for removing all documents matching the {@code filter}. * * @param filter The filter. * @param options The options. From f67af3f14be45e2cd95c77902ea7e816fcc25516 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 15:15:14 -0600 Subject: [PATCH 16/59] Move constructor methods to `ClientNamespacedWriteModel` JAVA-5527 --- .../model/bulk/ClientDeleteManyModel.java | 2 +- .../model/bulk/ClientDeleteOneModel.java | 2 +- .../bulk/ClientNamespacedWriteModel.java | 319 ++++++++++++++++++ .../client/model/bulk/ClientWriteModel.java | 266 --------------- .../bulk/ClientWriteModelWithNamespace.java | 30 -- ...> ConcreteClientNamespacedWriteModel.java} | 27 +- .../coroutine/syncadapter/SyncMongoCluster.kt | 10 +- .../client/syncadapter/SyncMongoCluster.kt | 10 +- .../client/syncadapter/SyncMongoClient.java | 10 +- .../client/syncadapter/SyncMongoCluster.java | 10 +- .../scala/syncadapter/SyncMongoCluster.scala | 10 +- .../main/com/mongodb/client/MongoCluster.java | 18 +- .../client/internal/MongoClientImpl.java | 10 +- .../client/internal/MongoClusterImpl.java | 10 +- 14 files changed, 380 insertions(+), 354 deletions(-) create mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java delete mode 100644 driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ConcreteClientWriteModelWithNamespace.java => ConcreteClientNamespacedWriteModel.java} (69%) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java index a5770169445..aba7af9d732 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java @@ -19,7 +19,7 @@ import com.mongodb.annotations.Sealed; /** - * A model for removing all documents matching a filter. + * A model for deleting all documents matching a filter. * * @since 5.3 */ diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java index 77ad1999680..c88c4d2ac12 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java @@ -19,7 +19,7 @@ import com.mongodb.annotations.Sealed; /** - * A model for removing at most one document matching a filter. + * A model for deleting at most one document matching a filter. * * @since 5.3 */ diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java new file mode 100644 index 00000000000..82d522780ba --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java @@ -0,0 +1,319 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.annotations.Sealed; +import com.mongodb.client.model.Aggregates; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Updates; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientInsertOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedWriteModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; +import org.bson.Document; +import org.bson.conversions.Bson; + +import static com.mongodb.assertions.Assertions.notNull; + +/** + * A combination of an {@linkplain ClientWriteModel individual write operation} and a {@linkplain MongoNamespace namespace} + * the operation is targeted at. + * + * @since 5.3 + */ +@Sealed +public interface ClientNamespacedWriteModel { + /** + * Creates a model for inserting the {@code document} into the {@code namespace}. + * + * @param namespace The namespace. + * @param document The document. + * @return The requested {@link ClientInsertOneModel} model with the {@code namespace}. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientNamespacedWriteModel insertOne(final MongoNamespace namespace, final TDocument document) { + notNull("namespace", namespace); + notNull("document", document); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientInsertOneModel(document)); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} matching the {@code filter}. + * This method is functionally equivalent to {@link #updateOne(MongoNamespace, Bson, Bson, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @see Filters + * @see Updates + */ + static ClientNamespacedWriteModel updateOne(final MongoNamespace namespace, final Bson filter, final Bson update) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, update, null, null)); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} matching the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @param options The options. + * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @see Filters + * @see Updates + */ + static ClientNamespacedWriteModel updateOne( + final MongoNamespace namespace, final Bson filter, final Bson update, final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + notNull("options", options); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, update, null, options)); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} matching the {@code filter}. + * This method is functionally equivalent to {@link #updateOne(MongoNamespace, Bson, Iterable, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @see Filters + * @see Aggregates + */ + static ClientNamespacedWriteModel updateOne(final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, null, updatePipeline, null)); + } + + /** + * Creates a model for updating at most one document in the {@code namespace} matching the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @param options The options. + * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @see Filters + * @see Aggregates + */ + static ClientNamespacedWriteModel updateOne( + final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + notNull("options", options); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, null, updatePipeline, options)); + } + + /** + * Creates a model for updating all documents in the {@code namespace} matching the {@code filter}. + * This method is functionally equivalent to {@link #updateMany(MongoNamespace, Bson, Bson, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @see Filters + * @see Updates + */ + static ClientNamespacedWriteModel updateMany(final MongoNamespace namespace, final Bson filter, final Bson update) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, update, null, null)); + } + + /** + * Creates a model for updating all documents in the {@code namespace} matching the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param update The update. + * @param options The options. + * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @see Filters + * @see Updates + */ + static ClientNamespacedWriteModel updateMany( + final MongoNamespace namespace, final Bson filter, final Bson update, final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("update", update); + notNull("options", options); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, update, null, options)); + } + + /** + * Creates a model for updating all documents in the {@code namespace} matching the {@code filter}. + * This method is functionally equivalent to {@link #updateMany(MongoNamespace, Bson, Iterable, ClientUpdateOptions)} + * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @see Filters + * @see Aggregates + */ + static ClientNamespacedWriteModel updateMany(final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, null, updatePipeline, null)); + } + + /** + * Creates a model for updating all documents in the {@code namespace} matching the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param updatePipeline The update pipeline. + * @param options The options. + * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @see Filters + * @see Aggregates + */ + static ClientNamespacedWriteModel updateMany( + final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("updatePipeline", updatePipeline); + notNull("options", options); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, null, updatePipeline, options)); + } + + /** + * Creates a model for replacing at most one document in the {@code namespace} matching the {@code filter}. + * This method is functionally equivalent to {@link #replaceOne(MongoNamespace, Bson, Object, ClientReplaceOptions)} + * with the {@linkplain ClientReplaceOptions#clientReplaceOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param replacement The replacement. + * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. + * @return The requested {@link ClientReplaceOneModel} model with the {@code namespace}. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientNamespacedWriteModel replaceOne(final MongoNamespace namespace, final Bson filter, final TDocument replacement) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("replacement", replacement); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientReplaceOneModel(filter, replacement, null)); + } + + /** + * Creates a model for replacing at most one document in the {@code namespace} matching the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param replacement The replacement. + * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. + * @param options The options. + * @return The requested {@link ClientReplaceOneModel} model with the {@code namespace}. + * @param The document type, for example {@link Document}. + * @see Filters + */ + static ClientNamespacedWriteModel replaceOne( + final MongoNamespace namespace, final Bson filter, final TDocument replacement, final ClientReplaceOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("replacement", replacement); + notNull("options", options); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientReplaceOneModel(filter, replacement, options)); + } + + /** + * Creates a model for deleting at most one document from the {@code namespace} matching the {@code filter}. + * This method is functionally equivalent to {@link #deleteOne(MongoNamespace, Bson, ClientDeleteOptions)} + * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @return The requested {@link ClientDeleteOneModel} model with the {@code namespace}. + * @see Filters + */ + static ClientNamespacedWriteModel deleteOne(final MongoNamespace namespace, final Bson filter) { + notNull("namespace", namespace); + notNull("filter", filter); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteOneModel(filter, null)); + } + + /** + * Creates a model for deleting at most one document from the {@code namespace} matching the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param options The options. + * @return The requested {@link ClientDeleteOneModel} model with the {@code namespace}. + * @see Filters + */ + static ClientNamespacedWriteModel deleteOne(final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("options", options); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteOneModel(filter, options)); + } + + /** + * Creates a model for deleting all documents from the {@code namespace} matching the {@code filter}. + * This method is functionally equivalent to {@link #deleteMany(MongoNamespace, Bson, ClientDeleteOptions)} + * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. + * + * @param namespace The namespace. + * @param filter The filter. + * @return The requested {@link ClientDeleteManyModel} model with the {@code namespace}. + * @see Filters + */ + static ClientNamespacedWriteModel deleteMany(final MongoNamespace namespace, final Bson filter) { + notNull("namespace", namespace); + notNull("filter", filter); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteManyModel(filter, null)); + } + + /** + * Creates a model for deleting all documents from the {@code namespace} matching the {@code filter}. + * + * @param namespace The namespace. + * @param filter The filter. + * @param options The options. + * @return The requested {@link ClientDeleteManyModel} model with the {@code namespace}. + * @see Filters + */ + static ClientNamespacedWriteModel deleteMany(final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { + notNull("namespace", namespace); + notNull("filter", filter); + notNull("options", options); + return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteManyModel(filter, options)); + } +} diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java index 0dc6e57499c..53f5adbd223 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java @@ -15,22 +15,7 @@ */ package com.mongodb.client.model.bulk; -import com.mongodb.MongoNamespace; import com.mongodb.annotations.Sealed; -import com.mongodb.client.model.Aggregates; -import com.mongodb.client.model.Filters; -import com.mongodb.client.model.Updates; -import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteManyModel; -import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOneModel; -import com.mongodb.internal.client.model.bulk.ConcreteClientInsertOneModel; -import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOneModel; -import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; -import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; -import com.mongodb.internal.client.model.bulk.ConcreteClientWriteModelWithNamespace; -import org.bson.Document; -import org.bson.conversions.Bson; - -import static com.mongodb.assertions.Assertions.notNull; /** * An individual write operation to be executed as part of a client-level bulk write operation. @@ -39,255 +24,4 @@ */ @Sealed public interface ClientWriteModel { - /** - * Creates a model for inserting the {@code document}. - * - * @param document The document. - * @return The requested model. - * @param The document type, for example {@link Document}. - * @see Filters - */ - static ClientInsertOneModel insertOne(final TDocument document) { - notNull("document", document); - return new ConcreteClientInsertOneModel(document); - } - - /** - * Creates a model for updating at most one document matching the {@code filter}. - * This method is functionally equivalent to {@link #updateOne(Bson, Bson, ClientUpdateOptions)} - * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. - * - * @param filter The filter. - * @param update The update. - * @return The requested model. - * @see Filters - * @see Updates - */ - static ClientUpdateOneModel updateOne(final Bson filter, final Bson update) { - notNull("filter", filter); - notNull("update", update); - return new ConcreteClientUpdateOneModel(filter, update, null, null); - } - - /** - * Creates a model for updating at most one document matching the {@code filter}. - * - * @param filter The filter. - * @param update The update. - * @param options The options. - * @return The requested model. - * @see Filters - * @see Updates - */ - static ClientUpdateOneModel updateOne(final Bson filter, final Bson update, final ClientUpdateOptions options) { - notNull("filter", filter); - notNull("update", update); - notNull("options", options); - return new ConcreteClientUpdateOneModel(filter, update, null, options); - } - - /** - * Creates a model for updating at most one document matching the {@code filter}. - * This method is functionally equivalent to {@link #updateOne(Bson, Iterable, ClientUpdateOptions)} - * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. - * - * @param filter The filter. - * @param updatePipeline The update pipeline. - * @return The requested model. - * @see Filters - * @see Aggregates - */ - static ClientUpdateOneModel updateOne(final Bson filter, final Iterable updatePipeline) { - notNull("filter", filter); - notNull("updatePipeline", updatePipeline); - return new ConcreteClientUpdateOneModel(filter, null, updatePipeline, null); - } - - /** - * Creates a model for updating at most one document matching the {@code filter}. - * - * @param filter The filter. - * @param updatePipeline The update pipeline. - * @param options The options. - * @return The requested model. - * @see Filters - * @see Aggregates - */ - static ClientUpdateOneModel updateOne(final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { - notNull("filter", filter); - notNull("updatePipeline", updatePipeline); - notNull("options", options); - return new ConcreteClientUpdateOneModel(filter, null, updatePipeline, options); - } - - /** - * Creates a model for updating all documents matching the {@code filter}. - * This method is functionally equivalent to {@link #updateMany(Bson, Bson, ClientUpdateOptions)} - * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default}. - * - * @param filter The filter. - * @param update The update. - * @return The requested model. - * @see Filters - * @see Updates - */ - static ClientUpdateManyModel updateMany(final Bson filter, final Bson update) { - notNull("filter", filter); - notNull("update", update); - return new ConcreteClientUpdateManyModel(filter, update, null, null); - } - - /** - * Creates a model for updating all documents matching the {@code filter}. - * - * @param filter The filter. - * @param update The update. - * @param options The options. - * @return The requested model. - * @see Filters - * @see Updates - */ - static ClientUpdateManyModel updateMany(final Bson filter, final Bson update, final ClientUpdateOptions options) { - notNull("filter", filter); - notNull("update", update); - notNull("options", options); - return new ConcreteClientUpdateManyModel(filter, update, null, options); - } - - /** - * Creates a model for updating all documents matching the {@code filter}. - * This method is functionally equivalent to {@link #updateMany(Bson, Iterable, ClientUpdateOptions)} - * with the {@linkplain ClientUpdateOptions#clientUpdateOptions() default options}. - * - * @param filter The filter. - * @param updatePipeline The update pipeline. - * @return The requested model. - * @see Filters - * @see Aggregates - */ - static ClientUpdateManyModel updateMany(final Bson filter, final Iterable updatePipeline) { - notNull("filter", filter); - notNull("updatePipeline", updatePipeline); - return new ConcreteClientUpdateManyModel(filter, null, updatePipeline, null); - } - - /** - * Creates a model for updating all documents matching the {@code filter}. - * - * @param filter The filter. - * @param updatePipeline The update pipeline. - * @param options The options. - * @return The requested model. - * @see Filters - * @see Aggregates - */ - static ClientUpdateManyModel updateMany(final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { - notNull("filter", filter); - notNull("updatePipeline", updatePipeline); - notNull("options", options); - return new ConcreteClientUpdateManyModel(filter, null, updatePipeline, options); - } - - /** - * Creates a model for replacing at most one document matching the {@code filter}. - * This method is functionally equivalent to {@link #replaceOne(Bson, Object, ClientReplaceOptions)} - * with the {@linkplain ClientReplaceOptions#clientReplaceOptions() default options}. - * - * @param filter The filter. - * @param replacement The replacement. - * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. - * @return The requested model. - * @param The document type, for example {@link Document}. - * @see Filters - */ - static ClientReplaceOneModel replaceOne(final Bson filter, final TDocument replacement) { - notNull("filter", filter); - notNull("replacement", replacement); - return new ConcreteClientReplaceOneModel(filter, replacement, null); - } - - /** - * Creates a model for replacing at most one document matching the {@code filter}. - * - * @param filter The filter. - * @param replacement The replacement. - * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. - * @param options The options. - * @return The requested model. - * @param The document type, for example {@link Document}. - * @see Filters - */ - static ClientReplaceOneModel replaceOne(final Bson filter, final TDocument replacement, final ClientReplaceOptions options) { - notNull("filter", filter); - notNull("replacement", replacement); - notNull("options", options); - return new ConcreteClientReplaceOneModel(filter, replacement, options); - } - - /** - * Creates a model for removing at most one document matching the {@code filter}. - * This method is functionally equivalent to {@link #deleteOne(Bson, ClientDeleteOptions)} - * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. - * - * @param filter The filter. - * @return The requested model. - * @see Filters - */ - static ClientDeleteOneModel deleteOne(final Bson filter) { - notNull("filter", filter); - return new ConcreteClientDeleteOneModel(filter, null); - } - - /** - * Creates a model for removing at most one document matching the {@code filter}. - * - * @param filter The filter. - * @param options The options. - * @return The requested model. - * @see Filters - */ - static ClientDeleteOneModel deleteOne(final Bson filter, final ClientDeleteOptions options) { - notNull("filter", filter); - notNull("options", options); - return new ConcreteClientDeleteOneModel(filter, options); - } - - /** - * Creates a model for removing all documents matching the {@code filter}. - * This method is functionally equivalent to {@link #deleteMany(Bson, ClientDeleteOptions)} - * with the {@linkplain ClientDeleteOptions#clientDeleteOptions() default options}. - * - * @param filter The filter. - * @return The requested model. - * @see Filters - */ - static ClientDeleteManyModel deleteMany(final Bson filter) { - notNull("filter", filter); - return new ConcreteClientDeleteManyModel(filter, null); - } - - /** - * Creates a model for removing all documents matching the {@code filter}. - * - * @param filter The filter. - * @param options The options. - * @return The requested model. - * @see Filters - */ - static ClientDeleteManyModel deleteMany(final Bson filter, final ClientDeleteOptions options) { - notNull("filter", filter); - notNull("options", options); - return new ConcreteClientDeleteManyModel(filter, options); - } - - /** - * Combines this model with the {@code namespace} it is targeted at. - * - * @param namespace The namespace. - * @return The model with the {@code namespace}. - */ - default ClientWriteModelWithNamespace withNamespace(final MongoNamespace namespace) { - notNull("namespace", namespace); - return new ConcreteClientWriteModelWithNamespace(this, namespace); - } } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java deleted file mode 100644 index d14f5bbf691..00000000000 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModelWithNamespace.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.mongodb.client.model.bulk; - -import com.mongodb.MongoNamespace; -import com.mongodb.annotations.Sealed; - -/** - * A combination of an {@linkplain ClientWriteModel individual write operation} and a {@linkplain MongoNamespace namespace} - * the operation is targeted at. - * - * @since 5.3 - */ -@Sealed -public interface ClientWriteModelWithNamespace { -} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientWriteModelWithNamespace.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java similarity index 69% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientWriteModelWithNamespace.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java index 10580fe27dc..8027fb73bce 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientWriteModelWithNamespace.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java @@ -17,31 +17,34 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.bulk.ClientWriteModel; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; -public final class ConcreteClientWriteModelWithNamespace implements ClientWriteModelWithNamespace { - private final ClientWriteModel model; +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientNamespacedWriteModel implements ClientNamespacedWriteModel { private final MongoNamespace namespace; + private final ClientWriteModel model; - public ConcreteClientWriteModelWithNamespace(final ClientWriteModel model, final MongoNamespace namespace) { - this.model = model; + public ConcreteClientNamespacedWriteModel(final MongoNamespace namespace, final ClientWriteModel model) { this.namespace = namespace; - } - - public ClientWriteModel getModel() { - return model; + this.model = model; } public MongoNamespace getNamespace() { return namespace; } + public ClientWriteModel getModel() { + return model; + } + @Override public String toString() { - return "ClientWriteModelWithNamespace{" - + "model=" + model - + ", namespace=" + namespace + return "ClientNamespacedWriteModel{" + + "namespace=" + namespace + + ", model=" + model + '}'; } } diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt index 68904e25a8b..e19f198e6d5 100644 --- a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt @@ -26,7 +26,7 @@ import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable import com.mongodb.client.model.bulk.ClientBulkWriteOptions -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.coroutine.MongoCluster import java.util.concurrent.TimeUnit @@ -114,12 +114,12 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) - override fun bulkWrite(models: MutableList): ClientBulkWriteResult { + override fun bulkWrite(models: MutableList): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") @@ -127,14 +127,14 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu override fun bulkWrite( clientSession: ClientSession, - models: MutableList + models: MutableList ): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( clientSession: ClientSession, - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt index 15336a821c9..24411058ff3 100644 --- a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt @@ -26,7 +26,7 @@ import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable import com.mongodb.client.model.bulk.ClientBulkWriteOptions -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.MongoCluster import java.util.concurrent.TimeUnit @@ -113,12 +113,12 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu ): ChangeStreamIterable = SyncChangeStreamIterable(wrapped.watch(clientSession.unwrapped(), pipeline, resultClass)) - override fun bulkWrite(models: MutableList): ClientBulkWriteResult { + override fun bulkWrite(models: MutableList): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") @@ -126,14 +126,14 @@ internal open class SyncMongoCluster(open val wrapped: MongoCluster) : JMongoClu override fun bulkWrite( clientSession: ClientSession, - models: MutableList + models: MutableList ): ClientBulkWriteResult { TODO("BULK-TODO implement") } override fun bulkWrite( clientSession: ClientSession, - models: MutableList, + models: MutableList, options: ClientBulkWriteOptions ): ClientBulkWriteResult { TODO("BULK-TODO implement") diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java index cd3bd2038cf..311297aec45 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java @@ -29,7 +29,7 @@ import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.reactivestreams.client.internal.BatchCursor; @@ -280,13 +280,13 @@ public void close() { @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels, options); } @@ -294,14 +294,14 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels, options); } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java index 105dae471ac..ec414b65160 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java @@ -29,7 +29,7 @@ import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import org.bson.BsonDocument; import org.bson.Document; @@ -285,13 +285,13 @@ public ChangeStreamIterable watch(final ClientSession clientS @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @@ -299,14 +299,14 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { throw Assertions.fail("BULK-TODO implement"); } diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala index 56b63b7d0f8..26ccbd65900 100644 --- a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala +++ b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala @@ -1,7 +1,7 @@ package org.mongodb.scala.syncadapter import com.mongodb.assertions.Assertions -import com.mongodb.client.model.bulk.{ ClientBulkWriteOptions, ClientWriteModelWithNamespace } +import com.mongodb.client.model.bulk.{ ClientBulkWriteOptions, ClientNamespacedWriteModel } import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.{ ClientSessionOptions, ReadConcern, ReadPreference, WriteConcern } import com.mongodb.client.{ ClientSession, MongoCluster => JMongoCluster, MongoDatabase => JMongoDatabase } @@ -129,25 +129,25 @@ class SyncMongoCluster(wrapped: MongoCluster) extends JMongoCluster { clientSession.asInstanceOf[SyncClientSession].wrapped override def bulkWrite( - models: util.List[_ <: ClientWriteModelWithNamespace] + models: util.List[_ <: ClientNamespacedWriteModel] ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") override def bulkWrite( - models: util.List[_ <: ClientWriteModelWithNamespace], + models: util.List[_ <: ClientNamespacedWriteModel], options: ClientBulkWriteOptions ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") override def bulkWrite( clientSession: ClientSession, - models: util.List[_ <: ClientWriteModelWithNamespace] + models: util.List[_ <: ClientNamespacedWriteModel] ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") override def bulkWrite( clientSession: ClientSession, - models: util.List[_ <: ClientWriteModelWithNamespace], + models: util.List[_ <: ClientNamespacedWriteModel], options: ClientBulkWriteOptions ): ClientBulkWriteResult = throw Assertions.fail("BULK-TODO implement") diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index 6bd6e9f26a0..c93b1a7299e 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -29,8 +29,8 @@ import com.mongodb.annotations.Reason; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; import com.mongodb.client.model.bulk.ClientDeleteManyModel; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.bulk.ClientUpdateManyModel; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.lang.Nullable; import org.bson.Document; @@ -372,7 +372,7 @@ public interface MongoCluster { * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* - * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. + * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: @@ -383,7 +383,7 @@ public interface MongoCluster { * @mongodb.server.release 8.0 * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ - ClientBulkWriteResult bulkWrite(List models) throws ClientBulkWriteException; + ClientBulkWriteResult bulkWrite(List models) throws ClientBulkWriteException; /** * Executes a client-level bulk write operation. @@ -394,7 +394,7 @@ public interface MongoCluster { * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* - * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. + * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. * @param options The options. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, @@ -407,7 +407,7 @@ public interface MongoCluster { * @mongodb.driver.manual reference/command/bulkWrite/ bulkWrite */ ClientBulkWriteResult bulkWrite( - List models, + List models, ClientBulkWriteOptions options) throws ClientBulkWriteException; /** @@ -422,7 +422,7 @@ ClientBulkWriteResult bulkWrite( * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. - * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. + * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, * and there is at least one of the following pieces of information to report: @@ -435,7 +435,7 @@ ClientBulkWriteResult bulkWrite( */ ClientBulkWriteResult bulkWrite( ClientSession clientSession, - List models) throws ClientBulkWriteException; + List models) throws ClientBulkWriteException; /** * Executes a client-level bulk write operation. @@ -447,7 +447,7 @@ ClientBulkWriteResult bulkWrite( * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

* * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. - * @param models The {@linkplain ClientWriteModelWithNamespace individual write operations}. + * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. * @param options The options. * @return The {@link ClientBulkWriteResult} if the operation is successful. * @throws ClientBulkWriteException If and only if the operation is unsuccessful or partially unsuccessful, @@ -461,6 +461,6 @@ ClientBulkWriteResult bulkWrite( */ ClientBulkWriteResult bulkWrite( ClientSession clientSession, - List models, + List models, ClientBulkWriteOptions options) throws ClientBulkWriteException; } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java index a3e10121c7f..894005467e1 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java @@ -33,7 +33,7 @@ import com.mongodb.client.MongoIterable; import com.mongodb.client.SynchronousContextProvider; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.connection.SocketSettings; @@ -262,13 +262,13 @@ public ChangeStreamIterable watch( @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientWriteModels, options); } @@ -276,14 +276,14 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels); } @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { return delegate.bulkWrite(clientSession, clientWriteModels, options); } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index 98ffff1ea85..462c7981f80 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -40,7 +40,7 @@ import com.mongodb.client.MongoIterable; import com.mongodb.client.SynchronousContextProvider; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.internal.IgnorableRequestContext; import com.mongodb.internal.TimeoutSettings; @@ -314,14 +314,14 @@ public ChangeStreamIterable watch(final ClientSession clientS @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); throw Assertions.fail("BULK-TODO implement"); } @Override public ClientBulkWriteResult bulkWrite( - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientWriteModels", clientWriteModels); notNull("options", options); @@ -331,7 +331,7 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels) throws ClientBulkWriteException { + final List clientWriteModels) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); throw Assertions.fail("BULK-TODO implement"); @@ -340,7 +340,7 @@ public ClientBulkWriteResult bulkWrite( @Override public ClientBulkWriteResult bulkWrite( final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, final ClientBulkWriteOptions options) throws ClientBulkWriteException { notNull("clientSession", clientSession); notNull("clientWriteModels", clientWriteModels); From 9a7b6682ddd6a1aa5e2fd64aff51b239ac28c63d Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 15:47:10 -0600 Subject: [PATCH 17/59] Fix errors caused by the merge JAVA-5528 --- .../operation/ClientBulkWriteOperation.java | 28 +++++------ .../internal/operation/Operations.java | 4 +- .../internal/operation/SyncOperations.java | 4 +- .../client/internal/MongoClusterImpl.java | 2 +- .../client/unified/UnifiedCrudHelper.java | 49 +++++++++++-------- 5 files changed, 47 insertions(+), 40 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index db558351e2e..38f03d6e840 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -38,7 +38,7 @@ import com.mongodb.client.model.bulk.ClientUpdateManyModel; import com.mongodb.client.model.bulk.ClientUpdateOneModel; import com.mongodb.client.model.bulk.ClientWriteModel; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.client.result.bulk.ClientDeleteResult; import com.mongodb.client.result.bulk.ClientInsertOneResult; @@ -58,7 +58,7 @@ import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOptions; -import com.mongodb.internal.client.model.bulk.ConcreteClientWriteModelWithNamespace; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedWriteModel; import com.mongodb.internal.client.result.bulk.AcknowledgedSummaryClientBulkWriteResult; import com.mongodb.internal.client.result.bulk.AcknowledgedVerboseClientBulkWriteResult; import com.mongodb.internal.client.result.bulk.ConcreteClientDeleteResult; @@ -132,7 +132,7 @@ public final class ClientBulkWriteOperation implements WriteOperation models; + private final List models; private final ConcreteClientBulkWriteOptions options; private final WriteConcern writeConcernSetting; private final boolean retryWritesSetting; @@ -142,7 +142,7 @@ public final class ClientBulkWriteOperation implements WriteOperation models, + final List models, @Nullable final ClientBulkWriteOptions options, final WriteConcern writeConcernSetting, final boolean retryWritesSetting, @@ -198,7 +198,7 @@ private Integer executeBatch( final WriteConcern effectiveWriteConcern, final WriteBinding binding, final ResultAccumulator resultAccumulator) { - List unexecutedModels = models.subList(batchStartModelIndex, models.size()); + List unexecutedModels = models.subList(batchStartModelIndex, models.size()); OperationContext operationContext = binding.getOperationContext(); SessionContext sessionContext = operationContext.getSessionContext(); TimeoutContext timeoutContext = operationContext.getTimeoutContext(); @@ -254,7 +254,7 @@ private ExhaustiveBulkWriteCommandOkResponse executeBulkWriteCommandAndExhaustOk final ConnectionSource connectionSource, final Connection connection, final BsonDocumentWrapper lazilyEncodedCommand, - final List unexecutedModels, + final List unexecutedModels, final WriteConcern effectiveWriteConcern, final OperationContext operationContext) throws MongoWriteConcernWithResponseException { BsonDocument bulkWriteCommandOkResponse = connection.command( @@ -321,7 +321,7 @@ private BsonDocumentWrapper createBulkWriteCommand( final boolean effectiveRetryWrites, final WriteConcern effectiveWriteConcern, final SessionContext sessionContext, - final List unexecutedModels, + final List unexecutedModels, final BatchEncoder batchEncoder, final Runnable ifCommandIsRetryable) { // BULK-TODO This implementation must limit the number of `models` it includes in a batch if needed. @@ -353,7 +353,7 @@ public void encode(final BsonWriter writer, final String commandName, final Enco writer.writeStartArray("ops"); boolean commandIsRetryable = effectiveRetryWrites; for (int modelIndexInBatch = 0; modelIndexInBatch < unexecutedModels.size(); modelIndexInBatch++) { - ConcreteClientWriteModelWithNamespace modelWithNamespace = getModelWithNamespace(unexecutedModels, modelIndexInBatch); + ConcreteClientNamespacedWriteModel modelWithNamespace = getModelWithNamespace(unexecutedModels, modelIndexInBatch); ClientWriteModel model = modelWithNamespace.getModel(); if (commandIsRetryable && !modelSupportsRetries.apply(model)) { commandIsRetryable = false; @@ -400,9 +400,9 @@ private void encodeUsingRegistry(final BsonWriter writer, final T value, fin collationEncoder.encode(writer, value, encoderContext); } - private static ConcreteClientWriteModelWithNamespace getModelWithNamespace( - final List models, final int index) { - return (ConcreteClientWriteModelWithNamespace) models.get(index); + private static ConcreteClientNamespacedWriteModel getModelWithNamespace( + final List models, final int index) { + return (ConcreteClientNamespacedWriteModel) models.get(index); } public static final class Exceptions { @@ -443,7 +443,7 @@ private static final class FieldNameValidators { *
  • if the name of the first field does not start with {@code '$'}, then the document is interpreted as a replacement.
  • * */ - private static FieldNameValidator createUpdateModsFieldValidator(final List models) { + private static FieldNameValidator createUpdateModsFieldValidator(final List models) { return new MappedFieldNameValidator( NoOpFieldNameValidator.INSTANCE, singletonMap("ops", new FieldNameValidators.OpsArrayFieldValidator(models))); @@ -452,12 +452,12 @@ private static FieldNameValidator createUpdateModsFieldValidator(final List OPERATION_DISCRIMINATOR_FIELD_NAMES = Stream.of("insert", "update", "delete").collect(toSet()); - private final List models; + private final List models; private final ReplacingUpdateModsFieldValidator replacingValidator; private final UpdatingUpdateModsFieldValidator updatingValidator; private int currentIndividualOperationIndex; - OpsArrayFieldValidator(final List models) { + OpsArrayFieldValidator(final List models) { this.models = models; replacingValidator = new ReplacingUpdateModsFieldValidator(); updatingValidator = new UpdatingUpdateModsFieldValidator(); diff --git a/driver-core/src/main/com/mongodb/internal/operation/Operations.java b/driver-core/src/main/com/mongodb/internal/operation/Operations.java index 4d4170bb5d3..b6fe8f4d19e 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/Operations.java +++ b/driver-core/src/main/com/mongodb/internal/operation/Operations.java @@ -55,7 +55,7 @@ import com.mongodb.client.model.ValidationOptions; import com.mongodb.client.model.WriteModel; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocumentBeforeChange; import com.mongodb.internal.bulk.DeleteRequest; @@ -721,7 +721,7 @@ ChangeStreamOperation changeStream(final FullDocument fullDoc } ClientBulkWriteOperation clientBulkWriteOperation( - final List clientWriteModels, + final List clientWriteModels, @Nullable final ClientBulkWriteOptions options) { return new ClientBulkWriteOperation(clientWriteModels, options, writeConcern, retryWrites, codecRegistry); } diff --git a/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java b/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java index 7f62cdba1f2..9680a23c9b1 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java +++ b/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java @@ -45,7 +45,7 @@ import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.model.WriteModel; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocumentBeforeChange; import com.mongodb.client.result.bulk.ClientBulkWriteResult; @@ -363,7 +363,7 @@ public ReadOperation> changeStream(final FullDocu } public WriteOperation clientBulkWriteOperation( - final List clientWriteModels, + final List clientWriteModels, @Nullable final ClientBulkWriteOptions options) { return operations.clientBulkWriteOperation(clientWriteModels, options); } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index 2c5d6a6129e..f1165651067 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -383,7 +383,7 @@ private ChangeStreamIterable createChangeStreamIterable(@Null private ClientBulkWriteResult executeBulkWrite( @Nullable final ClientSession clientSession, - final List clientWriteModels, + final List clientWriteModels, @Nullable final ClientBulkWriteOptions options) { isTrue("`autoEncryptionSettings` is null, as automatic encryption is not yet supported", autoEncryptionSettings == null); return operationExecutor.execute(operations.clientBulkWriteOperation(clientWriteModels, options), readConcern, clientSession); diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index c63075f315b..b26c3b0ac77 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -79,8 +79,7 @@ import com.mongodb.client.model.bulk.ClientDeleteOptions; import com.mongodb.client.model.bulk.ClientReplaceOptions; import com.mongodb.client.model.bulk.ClientUpdateOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; -import com.mongodb.client.model.bulk.ClientWriteModelWithNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocumentBeforeChange; @@ -1787,9 +1786,9 @@ public OperationResult clientBulkWrite(final BsonDocument operation) { MongoCluster cluster = entities.getClient(clientId); BsonDocument arguments = operation.getDocument("arguments"); ClientSession session = getSession(arguments); - List models = arguments.getArray("models").stream() + List models = arguments.getArray("models").stream() .map(BsonValue::asDocument) - .map(UnifiedCrudHelper::toClientWriteModelWithNamespace) + .map(UnifiedCrudHelper::toClientNamespacedWriteModel) .collect(toList()); ClientBulkWriteOptions options = clientBulkWriteOptions(); for (Map.Entry entry : arguments.entrySet()) { @@ -1831,7 +1830,7 @@ public OperationResult clientBulkWrite(final BsonDocument operation) { }); } - private static ClientWriteModelWithNamespace toClientWriteModelWithNamespace(final BsonDocument model) { + private static ClientNamespacedWriteModel toClientNamespacedWriteModel(final BsonDocument model) { String modelType = model.getFirstKey(); BsonDocument arguments = model.getDocument(modelType); MongoNamespace namespace = new MongoNamespace(arguments.getString("namespace").getValue()); @@ -1841,41 +1840,49 @@ private static ClientWriteModelWithNamespace toClientWriteModelWithNamespace(fin if (!expectedArguments.containsAll(arguments.keySet())) { throw new UnsupportedOperationException("Unsupported argument, one of: " + arguments.keySet()); } - return ClientWriteModel.insertOne( - arguments.getDocument("document")).withNamespace(namespace); + return ClientNamespacedWriteModel.insertOne( + namespace, + arguments.getDocument("document")); case "replaceOne": - return ClientWriteModel.replaceOne( + return ClientNamespacedWriteModel.replaceOne( + namespace, arguments.getDocument("filter"), arguments.getDocument("replacement"), - getClientReplaceOptions(arguments)).withNamespace(namespace); + getClientReplaceOptions(arguments)); case "updateOne": return arguments.isDocument("update") - ? ClientWriteModel.updateOne( + ? ClientNamespacedWriteModel.updateOne( + namespace, arguments.getDocument("filter"), arguments.getDocument("update"), - getClientUpdateOptions(arguments)).withNamespace(namespace) - : ClientWriteModel.updateOne( + getClientUpdateOptions(arguments)) + : ClientNamespacedWriteModel.updateOne( + namespace, arguments.getDocument("filter"), arguments.getArray("update").stream().map(BsonValue::asDocument).collect(toList()), - getClientUpdateOptions(arguments)).withNamespace(namespace); + getClientUpdateOptions(arguments)); case "updateMany": return arguments.isDocument("update") - ? ClientWriteModel.updateMany( + ? ClientNamespacedWriteModel.updateMany( + namespace, arguments.getDocument("filter"), arguments.getDocument("update"), - getClientUpdateOptions(arguments)).withNamespace(namespace) - : ClientWriteModel.updateMany( + getClientUpdateOptions(arguments)) + : ClientNamespacedWriteModel.updateMany( + namespace, arguments.getDocument("filter"), arguments.getArray("update").stream().map(BsonValue::asDocument).collect(toList()), - getClientUpdateOptions(arguments)).withNamespace(namespace); + getClientUpdateOptions(arguments)); case "deleteOne": - return ClientWriteModel.deleteOne( + return ClientNamespacedWriteModel.deleteOne( + namespace, arguments.getDocument("filter"), - getClientDeleteOptions(arguments)).withNamespace(namespace); + getClientDeleteOptions(arguments)); case "deleteMany": - return ClientWriteModel.deleteMany( + return ClientNamespacedWriteModel.deleteMany( + namespace, arguments.getDocument("filter"), - getClientDeleteOptions(arguments)).withNamespace(namespace); + getClientDeleteOptions(arguments)); default: throw new UnsupportedOperationException("Unsupported client write model type: " + modelType); } From 395af7a5f618321a1c8034950b1dd562e1992ae3 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 16:50:04 -0600 Subject: [PATCH 18/59] Use `Optional` to express verbose/summary results JAVA-5527 --- .../com/mongodb/ClientBulkWriteException.java | 6 +- .../model/bulk/ClientBulkWriteOptions.java | 2 +- .../result/bulk/ClientBulkWriteResult.java | 88 +++++++-------- ...nowledgedSummaryClientBulkWriteResult.java | 30 +----- ...nowledgedVerboseClientBulkWriteResult.java | 100 ++++++++++++------ .../UnacknowledgedClientBulkWriteResult.java | 22 +--- 6 files changed, 124 insertions(+), 124 deletions(-) diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index 1ed748989d7..aa69636cb36 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -118,9 +118,9 @@ public List getWriteConcernErrors() { * There are no guarantees on mutability or iteration order of the {@link Map} returned.

    * * @return The indexed {@link WriteError}s. - * @see ClientBulkWriteResult#getInsertResults() - * @see ClientBulkWriteResult#getUpdateResults() - * @see ClientBulkWriteResult#getDeleteResults() + * @see ClientBulkWriteResult.Verbose#getInsertResults() + * @see ClientBulkWriteResult.Verbose#getUpdateResults() + * @see ClientBulkWriteResult.Verbose#getDeleteResults() */ public Map getWriteErrors() { return writeErrors; diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java index 0ffce0c8063..e3e19d44041 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java @@ -80,7 +80,7 @@ static ClientBulkWriteOptions clientBulkWriteOptions() { ClientBulkWriteOptions comment(@Nullable BsonValue comment); /** - * Enables or disables requesting {@linkplain ClientBulkWriteResult#hasVerboseResults() verbose results}. + * Enables or disables requesting {@linkplain ClientBulkWriteResult#getVerbose() verbose results}. * * @param verboseResults The flag specifying whether to request verbose results. * If {@code null}, the client defaults to {@code false}. diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java index e6207826889..abc61b69d7d 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java @@ -23,6 +23,7 @@ import com.mongodb.client.model.bulk.ClientWriteModel; import java.util.Map; +import java.util.Optional; /** * The result of a successful or partially successful client-level bulk write operation. @@ -43,17 +44,6 @@ public interface ClientBulkWriteResult { */ boolean isAcknowledged(); - /** - * Indicates whether there are {@linkplain ClientBulkWriteOptions#verboseResults(Boolean) verbose results} - * of individual operations. - * If not, then {@link #getInsertResults()}, {@link #getUpdateResults()}, {@link #getDeleteResults()} - * throw {@link UnsupportedOperationException}. - * - * @return Whether there are verbose results. - * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. - */ - boolean hasVerboseResults(); - /** * The number of documents that were inserted across all insert operations. * @@ -95,44 +85,54 @@ public interface ClientBulkWriteResult { long getDeletedCount(); /** - * The indexed {@link ClientInsertOneResult}s. - * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s - * in the client-level bulk write operation. - *

    - * There are no guarantees on mutability or iteration order of the {@link Map} returned.

    + * The {@linkplain ClientBulkWriteOptions#verboseResults(Boolean) verbose results} of individual operations. * - * @return The indexed {@link ClientInsertOneResult}s. - * @throws UnsupportedOperationException If this result is either not {@linkplain #isAcknowledged() acknowledged}, - * or does not have {@linkplain #hasVerboseResults() verbose results}. - * @see ClientBulkWriteException#getWriteErrors() + * @return {@link Optional} verbose results of individual operations. + * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. */ - Map getInsertResults(); + Optional getVerbose(); /** - * The indexed {@link ClientUpdateResult}s. - * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s - * in the client-level bulk write operation. - *

    - * There are no guarantees on mutability or iteration order of the {@link Map} returned.

    + * The {@linkplain ClientBulkWriteResult#getVerbose() verbose results} of individual operations. * - * @return The indexed {@link ClientUpdateResult}s. - * @throws UnsupportedOperationException If this result is either not {@linkplain #isAcknowledged() acknowledged}, - * or does not have {@linkplain #hasVerboseResults() verbose results}. - * @see ClientBulkWriteException#getWriteErrors() + * @since 5.3 */ - Map getUpdateResults(); + @Evolving + interface Verbose { + /** + * The indexed {@link ClientInsertOneResult}s. + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * in the client-level bulk write operation. + *

    + * There are no guarantees on mutability or iteration order of the {@link Map} returned.

    + * + * @return The indexed {@link ClientInsertOneResult}s. + * @see ClientBulkWriteException#getWriteErrors() + */ + Map getInsertResults(); - /** - * The indexed {@link ClientDeleteResult}s. - * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s - * in the client-level bulk write operation. - *

    - * There are no guarantees on mutability or iteration order of the {@link Map} returned.

    - * - * @return The indexed {@link ClientDeleteResult}s. - * @throws UnsupportedOperationException If this result is either not {@linkplain #isAcknowledged() acknowledged}, - * or does not have {@linkplain #hasVerboseResults() verbose results}. - * @see ClientBulkWriteException#getWriteErrors() - */ - Map getDeleteResults(); + /** + * The indexed {@link ClientUpdateResult}s. + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * in the client-level bulk write operation. + *

    + * There are no guarantees on mutability or iteration order of the {@link Map} returned.

    + * + * @return The indexed {@link ClientUpdateResult}s. + * @see ClientBulkWriteException#getWriteErrors() + */ + Map getUpdateResults(); + + /** + * The indexed {@link ClientDeleteResult}s. + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * in the client-level bulk write operation. + *

    + * There are no guarantees on mutability or iteration order of the {@link Map} returned.

    + * + * @return The indexed {@link ClientDeleteResult}s. + * @see ClientBulkWriteException#getWriteErrors() + */ + Map getDeleteResults(); + } } diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java index 0123d3509e2..4f55be5e01b 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java @@ -16,12 +16,11 @@ package com.mongodb.internal.client.result.bulk; import com.mongodb.client.result.bulk.ClientBulkWriteResult; -import com.mongodb.client.result.bulk.ClientDeleteResult; -import com.mongodb.client.result.bulk.ClientInsertOneResult; -import com.mongodb.client.result.bulk.ClientUpdateResult; -import java.util.Map; import java.util.Objects; +import java.util.Optional; + +import static java.util.Optional.empty; /** * This class is not part of the public API and may be removed or changed at any time. @@ -51,11 +50,6 @@ public boolean isAcknowledged() { return true; } - @Override - public boolean hasVerboseResults() { - return false; - } - @Override public long getInsertedCount() { return insertedCount; @@ -82,22 +76,8 @@ public long getDeletedCount() { } @Override - public Map getInsertResults() throws UnsupportedOperationException { - throw noVerboseResultsException(); - } - - @Override - public Map getUpdateResults() throws UnsupportedOperationException { - throw noVerboseResultsException(); - } - - @Override - public Map getDeleteResults() throws UnsupportedOperationException { - throw noVerboseResultsException(); - } - - private static UnsupportedOperationException noVerboseResultsException() { - return new UnsupportedOperationException("Verbose results are not available"); + public Optional getVerbose() { + return empty(); } @Override diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java index a84cb3dee54..e3b643a97bc 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -22,17 +22,16 @@ import java.util.Map; import java.util.Objects; +import java.util.Optional; -import static java.util.Collections.unmodifiableMap; +import static java.util.Optional.of; /** * This class is not part of the public API and may be removed or changed at any time. */ public final class AcknowledgedVerboseClientBulkWriteResult implements ClientBulkWriteResult { private final AcknowledgedSummaryClientBulkWriteResult summaryResults; - private final Map insertResults; - private final Map updateResults; - private final Map deleteResults; + private final Verbose verbose; public AcknowledgedVerboseClientBulkWriteResult( final AcknowledgedSummaryClientBulkWriteResult summaryResults, @@ -40,9 +39,7 @@ public AcknowledgedVerboseClientBulkWriteResult( final Map updateResults, final Map deleteResults) { this.summaryResults = summaryResults; - this.insertResults = unmodifiableMap(insertResults); - this.updateResults = unmodifiableMap(updateResults); - this.deleteResults = unmodifiableMap(deleteResults); + this.verbose = new Verbose(insertResults, updateResults, deleteResults); } @Override @@ -50,11 +47,6 @@ public boolean isAcknowledged() { return true; } - @Override - public boolean hasVerboseResults() { - return true; - } - @Override public long getInsertedCount() { return summaryResults.getInsertedCount(); @@ -81,18 +73,8 @@ public long getDeletedCount() { } @Override - public Map getInsertResults() { - return insertResults; - } - - @Override - public Map getUpdateResults() { - return updateResults; - } - - @Override - public Map getDeleteResults() { - return deleteResults; + public Optional getVerbose() { + return of(verbose); } @Override @@ -105,14 +87,12 @@ public boolean equals(final Object o) { } final AcknowledgedVerboseClientBulkWriteResult that = (AcknowledgedVerboseClientBulkWriteResult) o; return Objects.equals(summaryResults, that.summaryResults) - && Objects.equals(insertResults, that.insertResults) - && Objects.equals(updateResults, that.updateResults) - && Objects.equals(deleteResults, that.deleteResults); + && Objects.equals(verbose, that.verbose); } @Override public int hashCode() { - return Objects.hash(summaryResults, insertResults, updateResults, deleteResults); + return Objects.hash(summaryResults, verbose); } @Override @@ -123,9 +103,67 @@ public String toString() { + ", matchedCount=" + summaryResults.getMatchedCount() + ", modifiedCount=" + summaryResults.getModifiedCount() + ", deletedCount=" + summaryResults.getDeletedCount() - + ", insertResults=" + insertResults - + ", updateResults=" + updateResults - + ", deleteResults=" + deleteResults + + ", insertResults=" + verbose.insertResults + + ", updateResults=" + verbose.updateResults + + ", deleteResults=" + verbose.deleteResults + '}'; } + + private static final class Verbose implements ClientBulkWriteResult.Verbose { + private final Map insertResults; + private final Map updateResults; + private final Map deleteResults; + + Verbose( + final Map insertResults, + final Map updateResults, + final Map deleteResults) { + this.insertResults = insertResults; + this.updateResults = updateResults; + this.deleteResults = deleteResults; + } + + @Override + public Map getInsertResults() { + return insertResults; + } + + @Override + public Map getUpdateResults() { + return updateResults; + } + + @Override + public Map getDeleteResults() { + return deleteResults; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Verbose verbose = (Verbose) o; + return Objects.equals(insertResults, verbose.insertResults) + && Objects.equals(updateResults, verbose.updateResults) + && Objects.equals(deleteResults, verbose.deleteResults); + } + + @Override + public int hashCode() { + return Objects.hash(insertResults, updateResults, deleteResults); + } + + @Override + public String toString() { + return "AcknowledgedVerboseClientBulkWriteResult.Verbose{" + + ", insertResults=" + insertResults + + ", updateResults=" + updateResults + + ", deleteResults=" + deleteResults + + '}'; + } + } } diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java index cf0525aa543..7288b4be333 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java @@ -17,11 +17,8 @@ import com.mongodb.annotations.Immutable; import com.mongodb.client.result.bulk.ClientBulkWriteResult; -import com.mongodb.client.result.bulk.ClientDeleteResult; -import com.mongodb.client.result.bulk.ClientInsertOneResult; -import com.mongodb.client.result.bulk.ClientUpdateResult; -import java.util.Map; +import java.util.Optional; /** * This class is not part of the public API and may be removed or changed at any time. @@ -38,11 +35,6 @@ public boolean isAcknowledged() { return false; } - @Override - public boolean hasVerboseResults() throws UnsupportedOperationException { - throw createUnacknowledgedResultsException(); - } - @Override public long getInsertedCount() throws UnsupportedOperationException { throw createUnacknowledgedResultsException(); @@ -69,17 +61,7 @@ public long getDeletedCount() throws UnsupportedOperationException { } @Override - public Map getInsertResults() throws UnsupportedOperationException { - throw createUnacknowledgedResultsException(); - } - - @Override - public Map getUpdateResults() throws UnsupportedOperationException { - throw createUnacknowledgedResultsException(); - } - - @Override - public Map getDeleteResults() throws UnsupportedOperationException { + public Optional getVerbose() throws UnsupportedOperationException { throw createUnacknowledgedResultsException(); } From b02a6385360d76b7305740022a27820831c0baa5 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 22 Aug 2024 17:31:16 -0600 Subject: [PATCH 19/59] Fix errors caused by the merge JAVA-5528 --- .../com/mongodb/client/unified/UnifiedCrudHelper.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index b26c3b0ac77..13182df25f0 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -1979,13 +1979,13 @@ static BsonDocument toMatchableValue(final ClientBulkWriteResult result) { .append("matchedCount", new BsonInt64(result.getMatchedCount())) .append("modifiedCount", new BsonInt64(result.getModifiedCount())) .append("deletedCount", new BsonInt64(result.getDeletedCount())); - if (result.hasVerboseResults()) { - expected.append("insertResults", new BsonDocument(result.getInsertResults().entrySet().stream() + result.getVerbose().ifPresent(verbose -> + expected.append("insertResults", new BsonDocument(verbose.getInsertResults().entrySet().stream() .map(entry -> new BsonElement( entry.getKey().toString(), new BsonDocument("insertedId", entry.getValue().getInsertedId()))) .collect(toList()))) - .append("updateResults", new BsonDocument(result.getUpdateResults().entrySet().stream() + .append("updateResults", new BsonDocument(verbose.getUpdateResults().entrySet().stream() .map(entry -> { ClientUpdateResult updateResult = entry.getValue(); BsonDocument updateResultDocument = new BsonDocument( @@ -1995,12 +1995,11 @@ static BsonDocument toMatchableValue(final ClientBulkWriteResult result) { return new BsonElement(entry.getKey().toString(), updateResultDocument); }) .collect(toList()))) - .append("deleteResults", new BsonDocument(result.getDeleteResults().entrySet().stream() + .append("deleteResults", new BsonDocument(verbose.getDeleteResults().entrySet().stream() .map(entry -> new BsonElement( entry.getKey().toString(), new BsonDocument("deletedCount", new BsonInt64(entry.getValue().getDeletedCount())))) - .collect(toList()))); - } + .collect(toList())))); } return expected; } From a11e5f6e46970321b86bc5e23b5762e2838ec5e5 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 26 Aug 2024 18:45:03 -0600 Subject: [PATCH 20/59] Make an API doc improvement JAVA-5527 --- .../com/mongodb/client/result/bulk/ClientBulkWriteResult.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java index abc61b69d7d..1420b1e571c 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java @@ -85,10 +85,11 @@ public interface ClientBulkWriteResult { long getDeletedCount(); /** - * The {@linkplain ClientBulkWriteOptions#verboseResults(Boolean) verbose results} of individual operations. + * The verbose results of individual operations. * * @return {@link Optional} verbose results of individual operations. * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. + * @see ClientBulkWriteOptions#verboseResults(Boolean) */ Optional getVerbose(); From bfbc1cc26685f2e0a76832a9d05d2e78dca94ac7 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 27 Aug 2024 12:03:44 -0600 Subject: [PATCH 21/59] Refactor `shouldAttemptToRetryWriteAndAddRetryableLabel` JAVA-5528 --- .../operation/AsyncOperationHelper.java | 2 +- .../operation/ClientBulkWriteOperation.java | 2 +- .../operation/CommandOperationHelper.java | 27 +++++++++++++------ .../operation/MixedBulkWriteOperation.java | 7 ++--- .../operation/SyncOperationHelper.java | 2 +- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java index ec9240065a8..072ae8e0d9f 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/AsyncOperationHelper.java @@ -322,7 +322,7 @@ static AsyncCallbackSupplier decorateReadWithRetriesAsync(final RetryStat static AsyncCallbackSupplier decorateWriteWithRetriesAsync(final RetryState retryState, final OperationContext operationContext, final AsyncCallbackSupplier asyncWriteFunction) { return new RetryingAsyncCallbackSupplier<>(retryState, onRetryableWriteAttemptFailure(operationContext), - CommandOperationHelper::shouldAttemptToRetryWriteAndAddRetryableLabel, callback -> { + CommandOperationHelper::loggingShouldAttemptToRetryWriteAndAddRetryableLabel, callback -> { logRetryExecute(retryState, operationContext); asyncWriteFunction.get(callback); }); diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index 38f03d6e840..b99fee6fda1 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -235,7 +235,7 @@ private Integer executeBatch( // The server does not have a chance to add "RetryableWriteError" label to `e`, // and if it is the last attempt failure, `RetryingSyncSupplier` also may not have a chance // to add the label. So we do that explicitly. - shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, e, false); + shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, e); resultAccumulator.onBulkWriteCommandErrorWithoutResponse(e); throw e; } diff --git a/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java index 4a2ee10e29a..e020a45df7a 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java @@ -41,6 +41,7 @@ import java.util.function.Supplier; import static com.mongodb.assertions.Assertions.assertFalse; +import static com.mongodb.assertions.Assertions.assertNotNull; import static com.mongodb.internal.operation.OperationHelper.LOGGER; import static java.lang.String.format; import static java.util.Arrays.asList; @@ -153,14 +154,26 @@ static boolean shouldAttemptToRetryRead(final RetryState retryState, final Throw return decision; } + static boolean loggingShouldAttemptToRetryWriteAndAddRetryableLabel(final RetryState retryState, final Throwable attemptFailure) { + Throwable attemptFailureNotToBeRetried = getAttemptFailureNotToRetryOrAddRetryableLabel(retryState, attemptFailure); + boolean decision = attemptFailureNotToBeRetried == null; + if (!decision && retryState.attachment(AttachmentKeys.retryableCommandFlag()).orElse(false)) { + logUnableToRetry( + retryState.attachment(AttachmentKeys.commandDescriptionSupplier()).orElse(null), + assertNotNull(attemptFailureNotToBeRetried)); + } + return decision; + } + static boolean shouldAttemptToRetryWriteAndAddRetryableLabel(final RetryState retryState, final Throwable attemptFailure) { - return shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, attemptFailure, true); + return getAttemptFailureNotToRetryOrAddRetryableLabel(retryState, attemptFailure) != null; } - static boolean shouldAttemptToRetryWriteAndAddRetryableLabel( - final RetryState retryState, - final Throwable attemptFailure, - final boolean logIfDecideToNotRetry) { + /** + * @return {@code null} if the decision is {@code true}. Otherwise, returns the {@link Throwable} that must not be retried. + */ + @Nullable + private static Throwable getAttemptFailureNotToRetryOrAddRetryableLabel(final RetryState retryState, final Throwable attemptFailure) { Throwable failure = attemptFailure instanceof ResourceSupplierInternalException ? attemptFailure.getCause() : attemptFailure; boolean decision = false; MongoException exceptionRetryableRegardlessOfCommand = null; @@ -177,11 +190,9 @@ static boolean shouldAttemptToRetryWriteAndAddRetryableLabel( } else if (decideRetryableAndAddRetryableWriteErrorLabel(failure, retryState.attachment(AttachmentKeys.maxWireVersion()) .orElse(null))) { decision = true; - } else if (logIfDecideToNotRetry) { - logUnableToRetry(retryState.attachment(AttachmentKeys.commandDescriptionSupplier()).orElse(null), failure); } } - return decision; + return decision ? null : assertNotNull(failure); } static boolean isRetryWritesEnabled(@Nullable final BsonDocument command) { diff --git a/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java index 01b1e362315..ef48b7075d2 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java @@ -63,6 +63,7 @@ import static com.mongodb.internal.operation.AsyncOperationHelper.withAsyncSourceAndConnection; import static com.mongodb.internal.operation.CommandOperationHelper.addRetryableWriteErrorLabel; import static com.mongodb.internal.operation.CommandOperationHelper.logRetryExecute; +import static com.mongodb.internal.operation.CommandOperationHelper.loggingShouldAttemptToRetryWriteAndAddRetryableLabel; import static com.mongodb.internal.operation.CommandOperationHelper.onRetryableWriteAttemptFailure; import static com.mongodb.internal.operation.CommandOperationHelper.transformWriteException; import static com.mongodb.internal.operation.OperationHelper.LOGGER; @@ -164,7 +165,7 @@ private boolean shouldAttemptToRetryWrite(final RetryState retryState, final Thr if (bulkWriteTracker.lastAttempt()) { return false; } - boolean decision = CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, attemptFailure); + boolean decision = loggingShouldAttemptToRetryWriteAndAddRetryableLabel(retryState, attemptFailure); if (decision) { /* The attempt counter maintained by `RetryState` is updated after (in the happens-before order) testing a retry predicate, * and only if the predicate completes normally. Here we maintain attempt counters manually, and we emulate the @@ -274,7 +275,7 @@ private BulkWriteResult executeBulkWriteBatch( if (currentBulkWriteTracker.lastAttempt()) { addRetryableWriteErrorLabel(writeConcernBasedError, maxWireVersion); addErrorLabelsToWriteConcern(result.getDocument("writeConcernError"), writeConcernBasedError.getErrorLabels()); - } else if (CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, writeConcernBasedError)) { + } else if (loggingShouldAttemptToRetryWriteAndAddRetryableLabel(retryState, writeConcernBasedError)) { throw new MongoWriteConcernWithResponseException(writeConcernBasedError, result); } } @@ -328,7 +329,7 @@ private void executeBulkWriteBatchAsync( addRetryableWriteErrorLabel(writeConcernBasedError, maxWireVersion); addErrorLabelsToWriteConcern(result.getDocument("writeConcernError"), writeConcernBasedError.getErrorLabels()); - } else if (CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel(retryState, writeConcernBasedError)) { + } else if (loggingShouldAttemptToRetryWriteAndAddRetryableLabel(retryState, writeConcernBasedError)) { iterationCallback.onResult(null, new MongoWriteConcernWithResponseException(writeConcernBasedError, result)); return; diff --git a/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java index b689a5aedd2..0d50768d668 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/SyncOperationHelper.java @@ -303,7 +303,7 @@ static T createReadCommandAndExecute( static Supplier decorateWriteWithRetries(final RetryState retryState, final OperationContext operationContext, final Supplier writeFunction) { return new RetryingSyncSupplier<>(retryState, onRetryableWriteAttemptFailure(operationContext), - CommandOperationHelper::shouldAttemptToRetryWriteAndAddRetryableLabel, () -> { + CommandOperationHelper::loggingShouldAttemptToRetryWriteAndAddRetryableLabel, () -> { logRetryExecute(retryState, operationContext); return writeFunction.get(); }); From 1c3c590ce10bb5f4682ddaf2e3596636ca023700 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 27 Aug 2024 16:01:11 -0600 Subject: [PATCH 22/59] Improve `CrudProseTest.insertMustGenerateIdAtMostOnce` JAVA-5528 --- .../result/bulk/ClientInsertOneResult.java | 2 + .../com/mongodb/client/CrudProseTest.java | 110 +++++++++++++++--- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java index 92f0d7d93fa..cafc3409219 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java @@ -33,5 +33,7 @@ public interface ClientInsertOneResult { * * @return The {@code "_id"} of the inserted document. */ + // BULK-TODO return optional because of `RawBsonDocument`? + // BULK-TODO document this for both the old and the new API BsonValue getInsertedId(); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java index 5d3907bb210..65039fc0ef5 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java @@ -20,40 +20,59 @@ import com.mongodb.MongoWriteConcernException; import com.mongodb.MongoWriteException; import com.mongodb.ServerAddress; +import com.mongodb.assertions.Assertions; import com.mongodb.client.model.CreateCollectionOptions; import com.mongodb.client.model.Filters; +import com.mongodb.client.model.InsertOneModel; import com.mongodb.client.model.ValidationOptions; import com.mongodb.event.CommandListener; import com.mongodb.event.CommandStartedEvent; import org.bson.BsonArray; import org.bson.BsonDocument; +import org.bson.BsonDocumentWrapper; import org.bson.BsonInt32; import org.bson.BsonString; import org.bson.BsonValue; import org.bson.Document; +import org.bson.RawBsonDocument; +import org.bson.codecs.configuration.CodecRegistry; import org.bson.codecs.pojo.PojoCodecProvider; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Stream; import static com.mongodb.ClusterFixture.isDiscoverableReplicaSet; import static com.mongodb.ClusterFixture.serverVersionAtLeast; import static com.mongodb.MongoClientSettings.getDefaultCodecRegistry; import static com.mongodb.client.Fixture.getMongoClientSettingsBuilder; +import static com.mongodb.client.model.bulk.ClientBulkWriteOptions.clientBulkWriteOptions; +import static com.mongodb.client.model.bulk.ClientNamespacedWriteModel.insertOne; import static java.lang.String.format; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.bson.codecs.configuration.CodecRegistries.fromProviders; import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.junit.jupiter.params.provider.Arguments.arguments; /** * See https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.rst#prose-tests @@ -131,9 +150,54 @@ public void testWriteErrorDetailsIsPropagated() { /** * This test is not from the specification. */ - @Test + @ParameterizedTest + @MethodSource("insertMustGenerateIdAtMostOnceArgs") + void insertMustGenerateIdAtMostOnce( + final Class documentClass, + final boolean expectIdGenerated, + final Supplier documentSupplier) { + assertAll( + () -> assertInsertMustGenerateIdAtMostOnce("insert", documentClass, expectIdGenerated, + (client, collection) -> collection.insertOne(documentSupplier.get()).getInsertedId()), + () -> assertInsertMustGenerateIdAtMostOnce("insert", documentClass, expectIdGenerated, + (client, collection) -> collection.bulkWrite( + singletonList(new InsertOneModel<>(documentSupplier.get()))) + .getInserts().get(0).getId()), + () -> assertInsertMustGenerateIdAtMostOnce("bulkWrite", documentClass, expectIdGenerated, + (client, collection) -> client.bulkWrite( + singletonList(insertOne(collection.getNamespace(), documentSupplier.get())), + clientBulkWriteOptions().verboseResults(true)) + // BULK-TODO use Integer instead of Long in BulkWriteResult.insertResults/updateResults/deleteResults + .getVerbose().orElseThrow(Assertions::fail).getInsertResults().get(0L).getInsertedId()) + ); + } + + private static Stream insertMustGenerateIdAtMostOnceArgs() { + CodecRegistry codecRegistry = fromRegistries( + getDefaultCodecRegistry(), + fromProviders(PojoCodecProvider.builder().automatic(true).build())); + return Stream.of( + arguments(MyDocument.class, true, (Supplier) MyDocument::new), + arguments(Document.class, true, (Supplier) Document::new), + arguments(BsonDocument.class, true, (Supplier) BsonDocument::new), + arguments( + BsonDocumentWrapper.class, true, + (Supplier>) () -> + new BsonDocumentWrapper<>(new MyDocument(), codecRegistry.get(MyDocument.class))), + arguments( + RawBsonDocument.class, false, + (Supplier) () -> + new RawBsonDocument(new MyDocument(), codecRegistry.get(MyDocument.class))) + ); + } + @SuppressWarnings("try") - void insertMustGenerateIdAtMostOnce() throws ExecutionException, InterruptedException { + private void assertInsertMustGenerateIdAtMostOnce( + final String commandName, + final Class documentClass, + final boolean expectIdGenerated, + final BiFunction, BsonValue> insertOperation) + throws ExecutionException, InterruptedException, TimeoutException { assumeTrue(isDiscoverableReplicaSet()); ServerAddress primaryServerAddress = Fixture.getPrimary(); CompletableFuture futureIdGeneratedByFirstInsertAttempt = new CompletableFuture<>(); @@ -141,20 +205,34 @@ void insertMustGenerateIdAtMostOnce() throws ExecutionException, InterruptedExce CommandListener commandListener = new CommandListener() { @Override public void commandStarted(final CommandStartedEvent event) { - if (event.getCommandName().equals("insert")) { - BsonValue generatedId = event.getCommand().getArray("documents").get(0).asDocument().get("_id"); + Consumer generatedIdConsumer = generatedId -> { if (!futureIdGeneratedByFirstInsertAttempt.isDone()) { futureIdGeneratedByFirstInsertAttempt.complete(generatedId); } else { futureIdGeneratedBySecondInsertAttempt.complete(generatedId); } + }; + switch (event.getCommandName()) { + case "insert": { + Assertions.assertTrue(commandName.equals("insert")); + generatedIdConsumer.accept(event.getCommand().getArray("documents").get(0).asDocument().get("_id")); + break; + } + case "bulkWrite": { + Assertions.assertTrue(commandName.equals("bulkWrite")); + generatedIdConsumer.accept(event.getCommand().getArray("ops").get(0).asDocument().getDocument("document").get("_id")); + break; + } + default: { + // nothing to do + } } } }; BsonDocument failPointDocument = new BsonDocument("configureFailPoint", new BsonString("failCommand")) .append("mode", new BsonDocument("times", new BsonInt32(1))) .append("data", new BsonDocument() - .append("failCommands", new BsonArray(singletonList(new BsonString("insert")))) + .append("failCommands", new BsonArray(singletonList(new BsonString(commandName)))) .append("errorLabels", new BsonArray(singletonList(new BsonString("RetryableWriteError")))) .append("writeConcernError", new BsonDocument("code", new BsonInt32(91)) .append("errmsg", new BsonString("Replication is being shut down")))); @@ -162,17 +240,23 @@ public void commandStarted(final CommandStartedEvent event) { .retryWrites(true) .addCommandListener(commandListener) .applyToServerSettings(builder -> builder.heartbeatFrequency(50, TimeUnit.MILLISECONDS)) + .codecRegistry(fromRegistries( + getDefaultCodecRegistry(), + fromProviders(PojoCodecProvider.builder().automatic(true).build()))) .build()); FailPoint ignored = FailPoint.enable(failPointDocument, primaryServerAddress)) { - MongoCollection coll = client.getDatabase(database.getName()) - .getCollection(collection.getNamespace().getCollectionName(), MyDocument.class) - .withCodecRegistry(fromRegistries( - getDefaultCodecRegistry(), - fromProviders(PojoCodecProvider.builder().automatic(true).build()))); - BsonValue insertedId = coll.insertOne(new MyDocument()).getInsertedId(); - BsonValue idGeneratedByFirstInsertAttempt = futureIdGeneratedByFirstInsertAttempt.get(); + MongoCollection coll = client.getDatabase(database.getName()) + .getCollection(collection.getNamespace().getCollectionName(), documentClass); + BsonValue insertedId = insertOperation.apply(client, coll); + if (expectIdGenerated) { + assertNotNull(insertedId); + } else { + assertNull(insertedId); + } + Duration timeout = Duration.ofSeconds(10); + BsonValue idGeneratedByFirstInsertAttempt = futureIdGeneratedByFirstInsertAttempt.get(timeout.toMillis(), TimeUnit.MILLISECONDS); assertEquals(idGeneratedByFirstInsertAttempt, insertedId); - assertEquals(idGeneratedByFirstInsertAttempt, futureIdGeneratedBySecondInsertAttempt.get()); + assertEquals(idGeneratedByFirstInsertAttempt, futureIdGeneratedBySecondInsertAttempt.get(timeout.toMillis(), TimeUnit.MILLISECONDS)); } } From 1c9c19e7344d410f4adf6b53bd59bdadd757cd41 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 27 Aug 2024 16:35:00 -0600 Subject: [PATCH 23/59] Move `MixedBulkWriteOperation.validateAndGetEffectiveWriteConcern`/`commandWriteConcern` to `CommandOperationHelper` JAVA-5528 --- .../internal/operation/BulkWriteBatch.java | 2 +- .../operation/ClientBulkWriteOperation.java | 4 ++-- .../operation/CommandOperationHelper.java | 20 +++++++++++++++++++ .../operation/MixedBulkWriteOperation.java | 20 +------------------ 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java b/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java index 84d7dd2c4c0..8da0f13e312 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java +++ b/driver-core/src/main/com/mongodb/internal/operation/BulkWriteBatch.java @@ -64,7 +64,7 @@ import static com.mongodb.internal.bulk.WriteRequest.Type.REPLACE; import static com.mongodb.internal.bulk.WriteRequest.Type.UPDATE; import static com.mongodb.internal.operation.DocumentHelper.putIfNotNull; -import static com.mongodb.internal.operation.MixedBulkWriteOperation.commandWriteConcern; +import static com.mongodb.internal.operation.CommandOperationHelper.commandWriteConcern; import static com.mongodb.internal.operation.OperationHelper.LOGGER; import static com.mongodb.internal.operation.OperationHelper.isRetryableWrite; import static com.mongodb.internal.operation.WriteConcernHelper.createWriteConcernError; diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index b99fee6fda1..fcaa57e3ec4 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -106,8 +106,8 @@ import static com.mongodb.internal.operation.CommandOperationHelper.initialRetryState; import static com.mongodb.internal.operation.CommandOperationHelper.shouldAttemptToRetryWriteAndAddRetryableLabel; import static com.mongodb.internal.operation.CommandOperationHelper.transformWriteException; -import static com.mongodb.internal.operation.MixedBulkWriteOperation.commandWriteConcern; -import static com.mongodb.internal.operation.MixedBulkWriteOperation.validateAndGetEffectiveWriteConcern; +import static com.mongodb.internal.operation.CommandOperationHelper.commandWriteConcern; +import static com.mongodb.internal.operation.CommandOperationHelper.validateAndGetEffectiveWriteConcern; import static com.mongodb.internal.operation.OperationHelper.isRetryableWrite; import static com.mongodb.internal.operation.SyncOperationHelper.cursorDocumentToBatchCursor; import static com.mongodb.internal.operation.SyncOperationHelper.decorateWriteWithRetries; diff --git a/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java index e020a45df7a..2861bcf9ad5 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/CommandOperationHelper.java @@ -25,6 +25,7 @@ import com.mongodb.MongoSecurityException; import com.mongodb.MongoServerException; import com.mongodb.MongoSocketException; +import com.mongodb.WriteConcern; import com.mongodb.assertions.Assertions; import com.mongodb.connection.ConnectionDescription; import com.mongodb.connection.ServerDescription; @@ -33,10 +34,12 @@ import com.mongodb.internal.connection.OperationContext; import com.mongodb.internal.operation.OperationHelper.ResourceSupplierInternalException; import com.mongodb.internal.operation.retry.AttachmentKeys; +import com.mongodb.internal.session.SessionContext; import com.mongodb.lang.Nullable; import org.bson.BsonDocument; import java.util.List; +import java.util.Optional; import java.util.function.BinaryOperator; import java.util.function.Supplier; @@ -48,6 +51,23 @@ @SuppressWarnings("overloads") final class CommandOperationHelper { + static WriteConcern validateAndGetEffectiveWriteConcern(final WriteConcern writeConcernSetting, final SessionContext sessionContext) + throws MongoClientException { + boolean activeTransaction = sessionContext.hasActiveTransaction(); + WriteConcern effectiveWriteConcern = activeTransaction + ? WriteConcern.ACKNOWLEDGED + : writeConcernSetting; + if (sessionContext.hasSession() && !sessionContext.isImplicitSession() && !activeTransaction && !effectiveWriteConcern.isAcknowledged()) { + throw new MongoClientException("Unacknowledged writes are not supported when using an explicit session"); + } + return effectiveWriteConcern; + } + + static Optional commandWriteConcern(final WriteConcern effectiveWriteConcern, final SessionContext sessionContext) { + return effectiveWriteConcern.isServerDefault() || sessionContext.hasActiveTransaction() + ? Optional.empty() + : Optional.of(effectiveWriteConcern); + } interface CommandCreator { BsonDocument create( diff --git a/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java index ef48b7075d2..28742574eb4 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java @@ -16,7 +16,6 @@ package com.mongodb.internal.operation; -import com.mongodb.MongoClientException; import com.mongodb.MongoException; import com.mongodb.MongoNamespace; import com.mongodb.WriteConcern; @@ -66,6 +65,7 @@ import static com.mongodb.internal.operation.CommandOperationHelper.loggingShouldAttemptToRetryWriteAndAddRetryableLabel; import static com.mongodb.internal.operation.CommandOperationHelper.onRetryableWriteAttemptFailure; import static com.mongodb.internal.operation.CommandOperationHelper.transformWriteException; +import static com.mongodb.internal.operation.CommandOperationHelper.validateAndGetEffectiveWriteConcern; import static com.mongodb.internal.operation.OperationHelper.LOGGER; import static com.mongodb.internal.operation.OperationHelper.isRetryableWrite; import static com.mongodb.internal.operation.OperationHelper.validateWriteRequests; @@ -436,24 +436,6 @@ operationContext, shouldExpectResponse(batch, effectiveWriteConcern), batch.getPayload(), batch.getFieldNameValidator(), callback); } - static WriteConcern validateAndGetEffectiveWriteConcern(final WriteConcern writeConcernSetting, final SessionContext sessionContext) - throws MongoClientException { - boolean activeTransaction = sessionContext.hasActiveTransaction(); - WriteConcern effectiveWriteConcern = activeTransaction - ? WriteConcern.ACKNOWLEDGED - : writeConcernSetting; - if (sessionContext.hasSession() && !sessionContext.isImplicitSession() && !activeTransaction && !effectiveWriteConcern.isAcknowledged()) { - throw new MongoClientException("Unacknowledged writes are not supported when using an explicit session"); - } - return effectiveWriteConcern; - } - - static Optional commandWriteConcern(final WriteConcern effectiveWriteConcern, final SessionContext sessionContext) { - return effectiveWriteConcern.isServerDefault() || sessionContext.hasActiveTransaction() - ? Optional.empty() - : Optional.of(effectiveWriteConcern); - } - private boolean shouldExpectResponse(final BulkWriteBatch batch, final WriteConcern effectiveWriteConcern) { return effectiveWriteConcern.isAcknowledged() || (ordered && batch.hasAnotherBatch()); } From 061e605188f9e065fc2085a1c56f519d8a7b225e Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 27 Aug 2024 16:56:18 -0600 Subject: [PATCH 24/59] Add a comment in `toClientNamespacedWriteModel` JAVA-5528 --- .../functional/com/mongodb/client/unified/UnifiedCrudHelper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index 13182df25f0..076b4ae7e94 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -1838,6 +1838,7 @@ private static ClientNamespacedWriteModel toClientNamespacedWriteModel(final Bso case "insertOne": Set expectedArguments = new HashSet<>(asList("namespace", "document")); if (!expectedArguments.containsAll(arguments.keySet())) { + // for other `modelType`s a conceptually similar check is done when creating their options objects throw new UnsupportedOperationException("Unsupported argument, one of: " + arguments.keySet()); } return ClientNamespacedWriteModel.insertOne( From 832021696df48ec9bf3bc08a9bb44001c17e0da9 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 09:40:55 -0600 Subject: [PATCH 25/59] Use `CommandResultDocumentCodec` in `ClientBulkWriteOperation` JAVA-5528 --- .../internal/operation/BsonDocumentWrapperHelper.java | 8 +------- .../internal/operation/ClientBulkWriteOperation.java | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java b/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java index 13edabce032..5b0d45dfc65 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/BsonDocumentWrapperHelper.java @@ -16,7 +16,6 @@ package com.mongodb.internal.operation; -import org.bson.BsonArray; import org.bson.BsonDocument; import org.bson.BsonDocumentWrapper; @@ -26,12 +25,7 @@ final class BsonDocumentWrapperHelper { @SuppressWarnings("unchecked") static List toList(final BsonDocument result, final String fieldContainingWrappedArray) { - // BULK-TODO why does the expectation of this code fails? - BsonArray array = result.getArray(fieldContainingWrappedArray); - if (array instanceof BsonArrayWrapper) { - return ((BsonArrayWrapper) array).getWrappedArray(); - } - return (List) array.getValues(); + return ((BsonArrayWrapper) result.getArray(fieldContainingWrappedArray)).getWrappedArray(); } @SuppressWarnings("unchecked") diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index fcaa57e3ec4..e6a55a75dbc 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -262,7 +262,7 @@ private ExhaustiveBulkWriteCommandOkResponse executeBulkWriteCommandAndExhaustOk lazilyEncodedCommand, FieldNameValidators.createUpdateModsFieldValidator(unexecutedModels), null, - codecRegistry.get(BsonDocument.class), + CommandResultDocumentCodec.create(codecRegistry.get(BsonDocument.class), CommandBatchCursorHelper.FIRST_BATCH), operationContext, effectiveWriteConcern.isAcknowledged(), null, From f41ed59f5fbe2a836536fabe47e8b4181e4d6df4 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 12:24:03 -0600 Subject: [PATCH 26/59] Use `Integer` for indexes in `ClientBulkWriteResult.Verbose`. Make `ClientInsertOneResult.getInsertedId` null-able. JAVA-5527 --- .../result/bulk/ClientBulkWriteResult.java | 6 ++--- .../result/bulk/ClientInsertOneResult.java | 7 +++++- ...nowledgedVerboseClientBulkWriteResult.java | 24 +++++++++---------- .../bulk/ConcreteClientInsertOneResult.java | 5 +++- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java index 1420b1e571c..5b49f7e4586 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java @@ -110,7 +110,7 @@ interface Verbose { * @return The indexed {@link ClientInsertOneResult}s. * @see ClientBulkWriteException#getWriteErrors() */ - Map getInsertResults(); + Map getInsertResults(); /** * The indexed {@link ClientUpdateResult}s. @@ -122,7 +122,7 @@ interface Verbose { * @return The indexed {@link ClientUpdateResult}s. * @see ClientBulkWriteException#getWriteErrors() */ - Map getUpdateResults(); + Map getUpdateResults(); /** * The indexed {@link ClientDeleteResult}s. @@ -134,6 +134,6 @@ interface Verbose { * @return The indexed {@link ClientDeleteResult}s. * @see ClientBulkWriteException#getWriteErrors() */ - Map getDeleteResults(); + Map getDeleteResults(); } } diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java index 92f0d7d93fa..b5a9a140972 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java @@ -18,7 +18,9 @@ import com.mongodb.annotations.Evolving; import com.mongodb.bulk.WriteConcernError; import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.lang.Nullable; import org.bson.BsonValue; +import org.bson.RawBsonDocument; /** * The result of a successful {@linkplain ClientWriteModel individual insert one operation}. @@ -31,7 +33,10 @@ public interface ClientInsertOneResult { /** * The {@code "_id"} of the inserted document. * - * @return The {@code "_id"} of the inserted document. + * @return The {@code "_id"} of the inserted document, or {@code null} if one is not available, + * which happens when a {@link RawBsonDocument} without {@code "_id"} is inserted, + * because the driver does not generate missing {@code "_id"} fields for {@link RawBsonDocument}s. */ + @Nullable BsonValue getInsertedId(); } diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java index e3b643a97bc..dbd3ab65414 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -35,9 +35,9 @@ public final class AcknowledgedVerboseClientBulkWriteResult implements ClientBul public AcknowledgedVerboseClientBulkWriteResult( final AcknowledgedSummaryClientBulkWriteResult summaryResults, - final Map insertResults, - final Map updateResults, - final Map deleteResults) { + final Map insertResults, + final Map updateResults, + final Map deleteResults) { this.summaryResults = summaryResults; this.verbose = new Verbose(insertResults, updateResults, deleteResults); } @@ -110,31 +110,31 @@ public String toString() { } private static final class Verbose implements ClientBulkWriteResult.Verbose { - private final Map insertResults; - private final Map updateResults; - private final Map deleteResults; + private final Map insertResults; + private final Map updateResults; + private final Map deleteResults; Verbose( - final Map insertResults, - final Map updateResults, - final Map deleteResults) { + final Map insertResults, + final Map updateResults, + final Map deleteResults) { this.insertResults = insertResults; this.updateResults = updateResults; this.deleteResults = deleteResults; } @Override - public Map getInsertResults() { + public Map getInsertResults() { return insertResults; } @Override - public Map getUpdateResults() { + public Map getUpdateResults() { return updateResults; } @Override - public Map getDeleteResults() { + public Map getDeleteResults() { return deleteResults; } diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java index c1cdb9843ac..bde09242c99 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java @@ -16,6 +16,7 @@ package com.mongodb.internal.client.result.bulk; import com.mongodb.client.result.bulk.ClientInsertOneResult; +import com.mongodb.lang.Nullable; import org.bson.BsonValue; import java.util.Objects; @@ -24,13 +25,15 @@ * This class is not part of the public API and may be removed or changed at any time. */ public final class ConcreteClientInsertOneResult implements ClientInsertOneResult { + @Nullable private final BsonValue insertedId; - public ConcreteClientInsertOneResult(final BsonValue insertedId) { + public ConcreteClientInsertOneResult(@Nullable final BsonValue insertedId) { this.insertedId = insertedId; } @Override + @Nullable public BsonValue getInsertedId() { return insertedId; } From 4846e0bd4162caddbad6adb947f59a5e2e121a15 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 13:01:14 -0600 Subject: [PATCH 27/59] Use `Integer` for indexes in `ClientBulkWriteException`. JAVA-5527 --- .../src/main/com/mongodb/ClientBulkWriteException.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index aa69636cb36..82a183505d7 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -44,7 +44,7 @@ public final class ClientBulkWriteException extends MongoServerException { @Nullable private final MongoException error; private final List writeConcernErrors; - private final Map writeErrors; + private final Map writeErrors; @Nullable private final ClientBulkWriteResult partialResult; @@ -60,7 +60,7 @@ public final class ClientBulkWriteException extends MongoServerException { public ClientBulkWriteException( @Nullable final MongoException error, @Nullable final List writeConcernErrors, - @Nullable final Map writeErrors, + @Nullable final Map writeErrors, @Nullable final ClientBulkWriteResult partialResult, final ServerAddress serverAddress) { super(message(error, writeConcernErrors, writeErrors, partialResult, serverAddress), serverAddress); @@ -79,7 +79,7 @@ public ClientBulkWriteException( private static String message( @Nullable final MongoException error, @Nullable final List writeConcernErrors, - @Nullable final Map writeErrors, + @Nullable final Map writeErrors, @Nullable final ClientBulkWriteResult partialResult, final ServerAddress serverAddress) { return "Client-level bulk write operation error on server " + serverAddress + "." @@ -122,7 +122,7 @@ public List getWriteConcernErrors() { * @see ClientBulkWriteResult.Verbose#getUpdateResults() * @see ClientBulkWriteResult.Verbose#getDeleteResults() */ - public Map getWriteErrors() { + public Map getWriteErrors() { return writeErrors; } From dbf9a26b8c636a2a91e0132697cfe50c7073fbac Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 15:12:09 -0600 Subject: [PATCH 28/59] Take `ClientBulkWriteException` into account in `OperationExecutor.execute`, `ClientSession.withTransaction` JAVA-5527 --- .../internal/operation/OperationHelper.java | 21 ++++++++++++++++++- .../internal/OperationExecutorImpl.java | 11 ++++++---- .../client/internal/ClientSessionImpl.java | 4 +++- .../client/internal/MongoClusterImpl.java | 11 ++++++---- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/OperationHelper.java b/driver-core/src/main/com/mongodb/internal/operation/OperationHelper.java index ac69f8742c7..f65d856451d 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/OperationHelper.java +++ b/driver-core/src/main/com/mongodb/internal/operation/OperationHelper.java @@ -16,7 +16,9 @@ package com.mongodb.internal.operation; +import com.mongodb.ClientBulkWriteException; import com.mongodb.MongoClientException; +import com.mongodb.MongoException; import com.mongodb.WriteConcern; import com.mongodb.client.cursor.TimeoutMode; import com.mongodb.client.model.Collation; @@ -47,7 +49,10 @@ import static com.mongodb.internal.operation.ServerVersionHelper.serverIsLessThanVersionFourDotTwo; import static java.lang.String.format; -final class OperationHelper { +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class OperationHelper { public static final Logger LOGGER = Loggers.getLogger("operation"); static void validateCollationAndWriteConcern(@Nullable final Collation collation, final WriteConcern writeConcern) { @@ -202,6 +207,20 @@ static void setNonTailableCursorMaxTimeSupplier(final TimeoutMode timeoutMode, f } } + /** + * Returns the {@link MongoException} that carries or should carry + * the {@linkplain MongoException#getCode() error code} and {@linkplain MongoException#getErrorLabels() error labels}. + * This method is needed because exceptions like {@link ClientBulkWriteException} do not carry that data themselves. + */ + public static MongoException unwrap(final MongoException exception) { + MongoException result = exception; + if (exception instanceof ClientBulkWriteException) { + result = ((ClientBulkWriteException) exception).getError().orElse(exception); + } + return result; + } + + /** * This internal exception is used to *
      diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java index 1c89ab81d34..0a4b0318d1c 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java @@ -33,6 +33,7 @@ import com.mongodb.internal.connection.ReadConcernAwareNoOpSessionContext; import com.mongodb.internal.operation.AsyncReadOperation; import com.mongodb.internal.operation.AsyncWriteOperation; +import com.mongodb.internal.operation.OperationHelper; import com.mongodb.lang.Nullable; import com.mongodb.reactivestreams.client.ClientSession; import com.mongodb.reactivestreams.client.ReactiveContextProvider; @@ -96,8 +97,9 @@ public Mono execute(final AsyncReadOperation operation, final ReadPref sinkToCallback(sink).onResult(result, t); } })).doOnError((t) -> { - labelException(session, t); - unpinServerAddressOnTransientTransactionError(session, t); + Throwable exceptionToHandle = t instanceof MongoException ? OperationHelper.unwrap((MongoException) t) : t; + labelException(session, exceptionToHandle); + unpinServerAddressOnTransientTransactionError(session, exceptionToHandle); }); } }).subscribe(subscriber) @@ -126,8 +128,9 @@ public Mono execute(final AsyncWriteOperation operation, final ReadCon sinkToCallback(sink).onResult(result, t); } })).doOnError((t) -> { - labelException(session, t); - unpinServerAddressOnTransientTransactionError(session, t); + Throwable exceptionToHandle = t instanceof MongoException ? OperationHelper.unwrap((MongoException) t) : t; + labelException(session, exceptionToHandle); + unpinServerAddressOnTransientTransactionError(session, exceptionToHandle); }) ).subscribe(subscriber) ); diff --git a/driver-sync/src/main/com/mongodb/client/internal/ClientSessionImpl.java b/driver-sync/src/main/com/mongodb/client/internal/ClientSessionImpl.java index d3bbd850ae0..b60fc90316a 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/ClientSessionImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/ClientSessionImpl.java @@ -30,6 +30,7 @@ import com.mongodb.internal.TimeoutContext; import com.mongodb.internal.operation.AbortTransactionOperation; import com.mongodb.internal.operation.CommitTransactionOperation; +import com.mongodb.internal.operation.OperationHelper; import com.mongodb.internal.operation.ReadOperation; import com.mongodb.internal.operation.WriteConcernHelper; import com.mongodb.internal.operation.WriteOperation; @@ -241,7 +242,8 @@ public T withTransaction(final TransactionBody transactionBody, final Tra abortTransaction(); } if (e instanceof MongoException && !(e instanceof MongoOperationTimeoutException)) { - if (((MongoException) e).hasErrorLabel(TRANSIENT_TRANSACTION_ERROR_LABEL) + MongoException exceptionToHandle = OperationHelper.unwrap((MongoException) e); + if (exceptionToHandle.hasErrorLabel(TRANSIENT_TRANSACTION_ERROR_LABEL) && ClientSessionClock.INSTANCE.now() - startTime < MAX_RETRY_TIME_LIMIT_MS) { continue; } diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index 462c7981f80..5b33898969e 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -53,6 +53,7 @@ import com.mongodb.internal.connection.Cluster; import com.mongodb.internal.connection.OperationContext; import com.mongodb.internal.connection.ReadConcernAwareNoOpSessionContext; +import com.mongodb.internal.operation.OperationHelper; import com.mongodb.internal.operation.ReadOperation; import com.mongodb.internal.operation.WriteOperation; import com.mongodb.internal.session.ServerSessionPool; @@ -398,8 +399,9 @@ public T execute(final ReadOperation operation, final ReadPreference read } return operation.execute(binding); } catch (MongoException e) { - labelException(actualClientSession, e); - clearTransactionContextOnTransientTransactionError(session, e); + MongoException exceptionToHandle = OperationHelper.unwrap(e); + labelException(actualClientSession, exceptionToHandle); + clearTransactionContextOnTransientTransactionError(session, exceptionToHandle); throw e; } finally { binding.release(); @@ -419,8 +421,9 @@ public T execute(final WriteOperation operation, final ReadConcern readCo try { return operation.execute(binding); } catch (MongoException e) { - labelException(actualClientSession, e); - clearTransactionContextOnTransientTransactionError(session, e); + MongoException exceptionToHandle = OperationHelper.unwrap(e); + labelException(actualClientSession, exceptionToHandle); + clearTransactionContextOnTransientTransactionError(session, exceptionToHandle); throw e; } finally { binding.release(); From 35eee966ce29376098becdc406d2987afc4f1769 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 15:34:26 -0600 Subject: [PATCH 29/59] Fixes after the merge JAVA-5528 --- .../operation/ClientBulkWriteOperation.java | 16 ++++++++-------- .../com/mongodb/client/CrudProseTest.java | 3 +-- .../com/mongodb/client/unified/ErrorMatcher.java | 6 +++--- .../client/unified/UnifiedCrudHelper.java | 3 ++- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index e6a55a75dbc..6ec3c838576 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -658,11 +658,11 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final long matchedCount = 0; long modifiedCount = 0; long deletedCount = 0; - Map insertResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); - Map updateResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); - Map deleteResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); + Map insertResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); + Map updateResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); + Map deleteResults = verboseResultsSetting ? new HashMap<>() : emptyMap(); ArrayList writeConcernErrors = new ArrayList<>(); - Map writeErrors = new HashMap<>(); + Map writeErrors = new HashMap<>(); for (BatchResult batchResult : batchResults) { if (batchResult.hasResponse()) { haveResponses = true; @@ -688,19 +688,19 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final ClientWriteModel writeModel = getModelWithNamespace(models, writeModelIndexInBatch).getModel(); if (writeModel instanceof ClientInsertOneModel) { insertResults.put( - (long) writeModelIndexInBatch, + writeModelIndexInBatch, new ConcreteClientInsertOneResult(insertModelDocumentIds.get(individualOperationIndexInBatch))); } else if (writeModel instanceof ClientUpdateOneModel || writeModel instanceof ClientReplaceOneModel) { BsonDocument upsertedIdDocument = individualOperationResponse.getDocument("upserted", null); updateResults.put( - (long) writeModelIndexInBatch, + writeModelIndexInBatch, new ConcreteClientUpdateResult( individualOperationResponse.getInt32("n").getValue(), individualOperationResponse.getInt32("nModified").getValue(), upsertedIdDocument == null ? null : upsertedIdDocument.get("_id"))); } else if (writeModel instanceof ClientDeleteOneModel) { deleteResults.put( - (long) writeModelIndexInBatch, + writeModelIndexInBatch, new ConcreteClientDeleteResult(individualOperationResponse.getInt32("n").getValue())); } else { fail(writeModel.getClass().toString()); @@ -710,7 +710,7 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final individualOperationResponse.getInt32("code").getValue(), individualOperationResponse.getString("errmsg").getValue(), individualOperationResponse.getDocument("errInfo", new BsonDocument())); - writeErrors.put((long) writeModelIndexInBatch, individualOperationWriteError); + writeErrors.put(writeModelIndexInBatch, individualOperationWriteError); } } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java index 65039fc0ef5..74acd2e5777 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java @@ -167,8 +167,7 @@ void insertMustGenerateIdAtMostOnce( (client, collection) -> client.bulkWrite( singletonList(insertOne(collection.getNamespace(), documentSupplier.get())), clientBulkWriteOptions().verboseResults(true)) - // BULK-TODO use Integer instead of Long in BulkWriteResult.insertResults/updateResults/deleteResults - .getVerbose().orElseThrow(Assertions::fail).getInsertResults().get(0L).getInsertedId()) + .getVerbose().orElseThrow(Assertions::fail).getInsertResults().get(0).getInsertedId()) ); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java b/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java index b8692c53a1c..d82e4c6beb1 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/ErrorMatcher.java @@ -41,7 +41,7 @@ import java.util.Map; import java.util.Set; -import static java.lang.Long.parseLong; +import static java.lang.Integer.parseInt; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; import static org.junit.Assert.assertEquals; @@ -150,10 +150,10 @@ void assertErrorsMatch(final BsonDocument expectedError, final Exception e) { e instanceof ClientBulkWriteException); BsonDocument writeErrors = expectedError.getDocument("writeErrors"); ClientBulkWriteException actualException = (ClientBulkWriteException) e; - Map actualWriteErrors = actualException.getWriteErrors(); + Map actualWriteErrors = actualException.getWriteErrors(); assertEquals("The number of write errors must match", writeErrors.size(), actualWriteErrors.size()); writeErrors.forEach((index, writeError) -> { - WriteError actualWriteError = actualWriteErrors.get(parseLong(index)); + WriteError actualWriteError = actualWriteErrors.get(parseInt(index)); assertNotNull("Expected a write error with index " + index, actualWriteError); valueMatcher.assertValuesMatch(writeError, toMatchableValue(actualWriteError)); }); diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index 076b4ae7e94..2741c35f1e5 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -119,6 +119,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; +import static com.mongodb.assertions.Assertions.assertNotNull; import static com.mongodb.client.model.bulk.ClientBulkWriteOptions.clientBulkWriteOptions; import static com.mongodb.client.model.bulk.ClientDeleteOptions.clientDeleteOptions; import static com.mongodb.client.model.bulk.ClientReplaceOptions.clientReplaceOptions; @@ -1984,7 +1985,7 @@ static BsonDocument toMatchableValue(final ClientBulkWriteResult result) { expected.append("insertResults", new BsonDocument(verbose.getInsertResults().entrySet().stream() .map(entry -> new BsonElement( entry.getKey().toString(), - new BsonDocument("insertedId", entry.getValue().getInsertedId()))) + new BsonDocument("insertedId", assertNotNull(entry.getValue().getInsertedId())))) .collect(toList()))) .append("updateResults", new BsonDocument(verbose.getUpdateResults().entrySet().stream() .map(entry -> { From 21bb22e85c340b025a9c4619f8c9255402cd9d47 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 17:00:31 -0600 Subject: [PATCH 30/59] Make `ClientInsertOneResult.getInsertedId` return `Optional` JAVA-5527 --- .../client/result/bulk/ClientInsertOneResult.java | 13 +++++++------ .../result/bulk/ConcreteClientInsertOneResult.java | 8 +++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java index b5a9a140972..60ea4581ac0 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java @@ -18,10 +18,11 @@ import com.mongodb.annotations.Evolving; import com.mongodb.bulk.WriteConcernError; import com.mongodb.client.model.bulk.ClientWriteModel; -import com.mongodb.lang.Nullable; import org.bson.BsonValue; import org.bson.RawBsonDocument; +import java.util.Optional; + /** * The result of a successful {@linkplain ClientWriteModel individual insert one operation}. * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. @@ -33,10 +34,10 @@ public interface ClientInsertOneResult { /** * The {@code "_id"} of the inserted document. * - * @return The {@code "_id"} of the inserted document, or {@code null} if one is not available, - * which happens when a {@link RawBsonDocument} without {@code "_id"} is inserted, - * because the driver does not generate missing {@code "_id"} fields for {@link RawBsonDocument}s. + * @return The {@code "_id"} of the inserted document. + * {@linkplain Optional#isPresent() Present} unless a {@link RawBsonDocument} is inserted, + * because the driver neither generates the missing {@code "_id"} field for a {@link RawBsonDocument}, + * nor does it read the {@code "_id"} field from a {@link RawBsonDocument} when inserting it. */ - @Nullable - BsonValue getInsertedId(); + Optional getInsertedId(); } diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java index bde09242c99..7cb439388e1 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java @@ -20,6 +20,9 @@ import org.bson.BsonValue; import java.util.Objects; +import java.util.Optional; + +import static java.util.Optional.ofNullable; /** * This class is not part of the public API and may be removed or changed at any time. @@ -33,9 +36,8 @@ public ConcreteClientInsertOneResult(@Nullable final BsonValue insertedId) { } @Override - @Nullable - public BsonValue getInsertedId() { - return insertedId; + public Optional getInsertedId() { + return ofNullable(insertedId); } @Override From fb32fde14043e506b9dc43fc1c31baac81a596a0 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 17:18:48 -0600 Subject: [PATCH 31/59] Fixes after the merge JAVA-5528 --- .../src/test/functional/com/mongodb/client/CrudProseTest.java | 2 +- .../com/mongodb/client/unified/UnifiedCrudHelper.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java index 74acd2e5777..3e4b91f5a4a 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java @@ -167,7 +167,7 @@ void insertMustGenerateIdAtMostOnce( (client, collection) -> client.bulkWrite( singletonList(insertOne(collection.getNamespace(), documentSupplier.get())), clientBulkWriteOptions().verboseResults(true)) - .getVerbose().orElseThrow(Assertions::fail).getInsertResults().get(0).getInsertedId()) + .getVerbose().orElseThrow(Assertions::fail).getInsertResults().get(0).getInsertedId().orElse(null)) ); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index 2741c35f1e5..7fc5d1de6d6 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -27,6 +27,7 @@ import com.mongodb.TagSet; import com.mongodb.TransactionOptions; import com.mongodb.WriteConcern; +import com.mongodb.assertions.Assertions; import com.mongodb.bulk.BulkWriteResult; import com.mongodb.client.AggregateIterable; import com.mongodb.client.ChangeStreamIterable; @@ -119,7 +120,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; -import static com.mongodb.assertions.Assertions.assertNotNull; import static com.mongodb.client.model.bulk.ClientBulkWriteOptions.clientBulkWriteOptions; import static com.mongodb.client.model.bulk.ClientDeleteOptions.clientDeleteOptions; import static com.mongodb.client.model.bulk.ClientReplaceOptions.clientReplaceOptions; @@ -1985,7 +1985,7 @@ static BsonDocument toMatchableValue(final ClientBulkWriteResult result) { expected.append("insertResults", new BsonDocument(verbose.getInsertResults().entrySet().stream() .map(entry -> new BsonElement( entry.getKey().toString(), - new BsonDocument("insertedId", assertNotNull(entry.getValue().getInsertedId())))) + new BsonDocument("insertedId", entry.getValue().getInsertedId().orElseThrow(Assertions::fail)))) .collect(toList()))) .append("updateResults", new BsonDocument(verbose.getUpdateResults().entrySet().stream() .map(entry -> { From f026ee3eb54b6f138d17c021121b314b306466b5 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 17:49:28 -0600 Subject: [PATCH 32/59] Update the documentation of `ClientBulkWriteException` and remove a TODO JAVA-5527 --- .../src/main/com/mongodb/ClientBulkWriteException.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index 82a183505d7..6e9af782b0c 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -33,6 +33,8 @@ /** * The result of an unsuccessful or partially unsuccessful client-level bulk write operation. + * Note that the {@linkplain #getCode() code} and {@linkplain #getErrorLabels() labels} from this exception are not useful. + * An application should use those from the {@linkplain #getError() top-level error}. * * @see ClientBulkWriteResult * @since 5.3 @@ -64,8 +66,6 @@ public ClientBulkWriteException( @Nullable final ClientBulkWriteResult partialResult, final ServerAddress serverAddress) { super(message(error, writeConcernErrors, writeErrors, partialResult, serverAddress), serverAddress); - // BULK-TODO Should ClientBulkWriteException.getCode be the same as error.getCode, - // and getErrorLabels/hasErrorLabel contain the same labels as error.getErrorLabels? isTrueArgument("At least one of `writeConcernErrors`, `writeErrors`, `partialResult` must be non-null or non-empty", !(writeConcernErrors == null || writeConcernErrors.isEmpty()) || !(writeErrors == null || writeErrors.isEmpty()) From 0fb65d47dd98fec5514900d1d7acad55839faa84 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 28 Aug 2024 21:16:49 -0600 Subject: [PATCH 33/59] Synchronize unified tests with https://github.com/mongodb/specifications/commit/0984b0942b9d8aaa11610184d0be16b27a263ec3 JAVA-5528 --- .../unacknowledged-client-bulkWrite.json | 3 ++- .../crud/client-bulkWrite-delete-options.json | 5 +++-- .../crud/client-bulkWrite-errorResponse.json | 3 ++- .../unified-test-format/crud/client-bulkWrite-errors.json | 3 ++- .../crud/client-bulkWrite-mixed-namespaces.json | 5 +++-- .../crud/client-bulkWrite-options.json | 5 +++-- .../crud/client-bulkWrite-ordered.json | 5 +++-- .../crud/client-bulkWrite-results.json | 5 +++-- .../crud/client-bulkWrite-update-options.json | 5 +++-- .../crud/client-bulkWrite-update-pipeline.json | 5 +++-- .../retryable-writes/client-bulkWrite-clientErrors.json | 3 ++- .../retryable-writes/client-bulkWrite-serverErrors.json | 3 ++- .../retryable-writes/handshakeError.json | 8 +++++--- .../server-selection/logging/operation-id.json | 6 ++++-- .../transactions/client-bulkWrite.json | 5 +++-- .../test/resources/versioned-api/crud-api-version-1.json | 3 ++- 16 files changed, 45 insertions(+), 27 deletions(-) diff --git a/driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json b/driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json index 1099b6a1e9f..b30e1540f45 100644 --- a/driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json +++ b/driver-core/src/test/resources/unified-test-format/command-monitoring/unacknowledged-client-bulkWrite.json @@ -3,7 +3,8 @@ "schemaVersion": "1.7", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json index 5bdf2b124a3..d9987897dcd 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-delete-options.json @@ -1,9 +1,10 @@ { "description": "client bulkWrite delete options", - "schemaVersion": "1.1", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json index edf2339d8a3..b828aad3b93 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errorResponse.json @@ -3,7 +3,8 @@ "schemaVersion": "1.12", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json index 9f17f85331d..8cc45bb5f2d 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-errors.json @@ -3,7 +3,8 @@ "schemaVersion": "1.21", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json index f90755dc850..55f06189233 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-mixed-namespaces.json @@ -1,9 +1,10 @@ { "description": "client bulkWrite with mixed namespaces", - "schemaVersion": "1.1", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json index a1e6af3bf3b..708fe4e85b0 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-options.json @@ -1,9 +1,10 @@ { "description": "client bulkWrite top-level options", - "schemaVersion": "1.1", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json index a55d6619b5e..6fb10d992f0 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-ordered.json @@ -1,9 +1,10 @@ { "description": "client bulkWrite with ordered option", - "schemaVersion": "1.1", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json index 97a9e50b217..accf5a9cbf5 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-results.json @@ -1,9 +1,10 @@ { "description": "client bulkWrite results", - "schemaVersion": "1.1", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json index 93a2774e5fa..ce6241c6812 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-options.json @@ -1,9 +1,10 @@ { "description": "client bulkWrite update options", - "schemaVersion": "1.1", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json index 57b6c9c1ba4..9dba5ee6c57 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json +++ b/driver-core/src/test/resources/unified-test-format/crud/client-bulkWrite-update-pipeline.json @@ -1,9 +1,10 @@ { "description": "client bulkWrite update pipeline", - "schemaVersion": "1.1", + "schemaVersion": "1.4", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json index e2c0fb9c0a5..d16e0c9c8d6 100644 --- a/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json +++ b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-clientErrors.json @@ -8,7 +8,8 @@ "replicaset", "sharded", "load-balanced" - ] + ], + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json index 4a0b210eb59..f58c82bcc73 100644 --- a/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json +++ b/driver-core/src/test/resources/unified-test-format/retryable-writes/client-bulkWrite-serverErrors.json @@ -8,7 +8,8 @@ "replicaset", "sharded", "load-balanced" - ] + ], + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json b/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json index 3c464637598..93cb2e849ec 100644 --- a/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json +++ b/driver-core/src/test/resources/unified-test-format/retryable-writes/handshakeError.json @@ -1,6 +1,6 @@ { "description": "retryable writes handshake failures", - "schemaVersion": "1.3", + "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.2", @@ -57,7 +57,8 @@ "description": "client.clientBulkWrite succeeds after retryable handshake network error", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "operations": [ @@ -165,7 +166,8 @@ "description": "client.clientBulkWrite succeeds after retryable handshake server error (ShutdownInProgress)", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "operations": [ diff --git a/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json b/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json index 6cdbcb3f5af..c1024184ffd 100644 --- a/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json +++ b/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json @@ -232,7 +232,8 @@ "description": "Successful client bulkWrite operation: log messages have operationIds", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "operations": [ @@ -304,7 +305,8 @@ "description": "Failed client bulkWrite operation: log messages have operationIds", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "operations": [ diff --git a/driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json b/driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json index f8f1d97169d..4a8d013f8d5 100644 --- a/driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json +++ b/driver-core/src/test/resources/unified-test-format/transactions/client-bulkWrite.json @@ -1,6 +1,6 @@ { "description": "client bulkWrite transactions", - "schemaVersion": "1.3", + "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "8.0", @@ -8,7 +8,8 @@ "replicaset", "sharded", "load-balanced" - ] + ], + "serverless": "forbid" } ], "createEntities": [ diff --git a/driver-core/src/test/resources/versioned-api/crud-api-version-1.json b/driver-core/src/test/resources/versioned-api/crud-api-version-1.json index fe668620f82..23ef59a6d98 100644 --- a/driver-core/src/test/resources/versioned-api/crud-api-version-1.json +++ b/driver-core/src/test/resources/versioned-api/crud-api-version-1.json @@ -431,7 +431,8 @@ "description": "client bulkWrite appends declared API version", "runOnRequirements": [ { - "minServerVersion": "8.0" + "minServerVersion": "8.0", + "serverless": "forbid" } ], "operations": [ From e36898f407bff2d8a3a80d26dd1f90c98370626c Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Thu, 29 Aug 2024 15:19:07 -0600 Subject: [PATCH 34/59] Refactor `CrudProseTest` to support the reactive client JAVA-5528 --- .../reactivestreams/client/CrudProseTest.java | 31 ++++ .../com/mongodb/client/CrudProseTest.java | 164 +++++++++--------- 2 files changed, 110 insertions(+), 85 deletions(-) create mode 100644 driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/CrudProseTest.java diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/CrudProseTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/CrudProseTest.java new file mode 100644 index 00000000000..81d88e6fdb0 --- /dev/null +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/CrudProseTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.reactivestreams.client; + +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; +import com.mongodb.reactivestreams.client.syncadapter.SyncMongoClient; + +/** + * See + * CRUD Prose Tests. + */ +final class CrudProseTest extends com.mongodb.client.CrudProseTest { + @Override + protected MongoClient createMongoClient(final MongoClientSettings.Builder mongoClientSettingsBuilder) { + return new SyncMongoClient(MongoClients.create(mongoClientSettingsBuilder.build())); + } +} diff --git a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java index 3e4b91f5a4a..7a669cab097 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java @@ -17,9 +17,10 @@ package com.mongodb.client; import com.mongodb.MongoBulkWriteException; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoNamespace; import com.mongodb.MongoWriteConcernException; import com.mongodb.MongoWriteException; -import com.mongodb.ServerAddress; import com.mongodb.assertions.Assertions; import com.mongodb.client.model.CreateCollectionOptions; import com.mongodb.client.model.Filters; @@ -37,7 +38,7 @@ import org.bson.RawBsonDocument; import org.bson.codecs.configuration.CodecRegistry; import org.bson.codecs.pojo.PojoCodecProvider; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -56,11 +57,11 @@ import static com.mongodb.ClusterFixture.isDiscoverableReplicaSet; import static com.mongodb.ClusterFixture.serverVersionAtLeast; import static com.mongodb.MongoClientSettings.getDefaultCodecRegistry; +import static com.mongodb.client.Fixture.getDefaultDatabaseName; import static com.mongodb.client.Fixture.getMongoClientSettingsBuilder; +import static com.mongodb.client.Fixture.getPrimary; import static com.mongodb.client.model.bulk.ClientBulkWriteOptions.clientBulkWriteOptions; import static com.mongodb.client.model.bulk.ClientNamespacedWriteModel.insertOne; -import static java.lang.String.format; -import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.bson.codecs.configuration.CodecRegistries.fromProviders; import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; @@ -69,81 +70,76 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.params.provider.Arguments.arguments; /** - * See https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.rst#prose-tests + * See + * CRUD Prose Tests. */ -public class CrudProseTest extends DatabaseTestCase { - private BsonDocument failPointDocument; - - @BeforeEach - @Override - public void setUp() { - super.setUp(); - } - - /** - * 1. WriteConcernError.details exposes writeConcernError.errInfo - */ +public class CrudProseTest { + @DisplayName("1. WriteConcernError.details exposes writeConcernError.errInfo") @Test - public void testWriteConcernErrInfoIsPropagated() { + @SuppressWarnings("try") + void testWriteConcernErrInfoIsPropagated() throws InterruptedException { assumeTrue(isDiscoverableReplicaSet() && serverVersionAtLeast(4, 0)); - - try { - setFailPoint(); - collection.insertOne(Document.parse("{ x: 1 }")); - } catch (MongoWriteConcernException e) { - assertEquals(e.getWriteConcernError().getCode(), 100); - assertEquals("UnsatisfiableWriteConcern", e.getWriteConcernError().getCodeName()); - assertEquals(e.getWriteConcernError().getDetails(), new BsonDocument("writeConcern", + BsonDocument failPointDocument = new BsonDocument("configureFailPoint", new BsonString("failCommand")) + .append("mode", new BsonDocument("times", new BsonInt32(1))) + .append("data", new BsonDocument("failCommands", new BsonArray(singletonList(new BsonString("insert")))) + .append("writeConcernError", new BsonDocument("code", new BsonInt32(100)) + .append("codeName", new BsonString("UnsatisfiableWriteConcern")) + .append("errmsg", new BsonString("Not enough data-bearing nodes")) + .append("errInfo", new BsonDocument("writeConcern", new BsonDocument("w", new BsonInt32(2)) + .append("wtimeout", new BsonInt32(0)) + .append("provenance", new BsonString("clientSupplied")))))); + try (MongoClient client = createMongoClient(getMongoClientSettingsBuilder()); + FailPoint ignored = FailPoint.enable(failPointDocument, getPrimary())) { + MongoWriteConcernException actual = assertThrows(MongoWriteConcernException.class, () -> + droppedCollection(client, Document.class).insertOne(Document.parse("{ x: 1 }"))); + assertEquals(actual.getWriteConcernError().getCode(), 100); + assertEquals("UnsatisfiableWriteConcern", actual.getWriteConcernError().getCodeName()); + assertEquals(actual.getWriteConcernError().getDetails(), new BsonDocument("writeConcern", new BsonDocument("w", new BsonInt32(2)) .append("wtimeout", new BsonInt32(0)) .append("provenance", new BsonString("clientSupplied")))); - } catch (Exception ex) { - fail(format("Incorrect exception thrown in test: %s", ex.getClass())); - } finally { - disableFailPoint(); } } - /** - * 2. WriteError.details exposes writeErrors[].errInfo - */ + @DisplayName("2. WriteError.details exposes writeErrors[].errInfo") @Test - public void testWriteErrorDetailsIsPropagated() { - getCollectionHelper().create(getCollectionName(), - new CreateCollectionOptions() - .validationOptions(new ValidationOptions() - .validator(Filters.type("x", "string")))); - - try { - collection.insertOne(new Document("x", 1)); - fail("Should throw, as document doesn't match schema"); - } catch (MongoWriteException e) { - // These assertions doesn't do exactly what's required by the specification, but it's simpler to implement and nearly as - // effective - assertTrue(e.getMessage().contains("Write error")); - assertNotNull(e.getError().getDetails()); - if (serverVersionAtLeast(5, 0)) { - assertFalse(e.getError().getDetails().isEmpty()); - } - } + void testWriteErrorDetailsIsPropagated() { + try (MongoClient client = createMongoClient(getMongoClientSettingsBuilder())) { + MongoCollection collection = droppedCollection(client, Document.class); + droppedDatabase(client).createCollection( + collection.getNamespace().getCollectionName(), + new CreateCollectionOptions().validationOptions(new ValidationOptions().validator(Filters.type("x", "string")))); + assertAll( + () -> { + MongoWriteException actual = assertThrows(MongoWriteException.class, () -> + collection.insertOne(new Document("x", 1))); + // These assertions don't do exactly what's required by the specification, + // but it's simpler to implement and nearly as effective. + assertTrue(actual.getMessage().contains("Write error")); + assertNotNull(actual.getError().getDetails()); + if (serverVersionAtLeast(5, 0)) { + assertFalse(actual.getError().getDetails().isEmpty()); + } + }, + () -> { + MongoBulkWriteException actual = assertThrows(MongoBulkWriteException.class, () -> + collection.insertMany(singletonList(new Document("x", 1)))); + // These assertions don't do exactly what's required by the specification, + // but it's simpler to implement and nearly as effective. + assertTrue(actual.getMessage().contains("Write errors")); + assertEquals(1, actual.getWriteErrors().size()); + if (serverVersionAtLeast(5, 0)) { + assertFalse(actual.getWriteErrors().get(0).getDetails().isEmpty()); + } + } + ); - try { - collection.insertMany(asList(new Document("x", 1))); - fail("Should throw, as document doesn't match schema"); - } catch (MongoBulkWriteException e) { - // These assertions doesn't do exactly what's required by the specification, but it's simpler to implement and nearly as - // effective - assertTrue(e.getMessage().contains("Write errors")); - assertEquals(1, e.getWriteErrors().size()); - if (serverVersionAtLeast(5, 0)) { - assertFalse(e.getWriteErrors().get(0).getDetails().isEmpty()); - } } } @@ -156,6 +152,7 @@ void insertMustGenerateIdAtMostOnce( final Class documentClass, final boolean expectIdGenerated, final Supplier documentSupplier) { + assumeTrue(isDiscoverableReplicaSet()); assertAll( () -> assertInsertMustGenerateIdAtMostOnce("insert", documentClass, expectIdGenerated, (client, collection) -> collection.insertOne(documentSupplier.get()).getInsertedId()), @@ -197,8 +194,6 @@ private void assertInsertMustGenerateIdAtMostOnce( final boolean expectIdGenerated, final BiFunction, BsonValue> insertOperation) throws ExecutionException, InterruptedException, TimeoutException { - assumeTrue(isDiscoverableReplicaSet()); - ServerAddress primaryServerAddress = Fixture.getPrimary(); CompletableFuture futureIdGeneratedByFirstInsertAttempt = new CompletableFuture<>(); CompletableFuture futureIdGeneratedBySecondInsertAttempt = new CompletableFuture<>(); CommandListener commandListener = new CommandListener() { @@ -235,18 +230,16 @@ public void commandStarted(final CommandStartedEvent event) { .append("errorLabels", new BsonArray(singletonList(new BsonString("RetryableWriteError")))) .append("writeConcernError", new BsonDocument("code", new BsonInt32(91)) .append("errmsg", new BsonString("Replication is being shut down")))); - try (MongoClient client = MongoClients.create(getMongoClientSettingsBuilder() + try (MongoClient client = createMongoClient(getMongoClientSettingsBuilder() .retryWrites(true) .addCommandListener(commandListener) .applyToServerSettings(builder -> builder.heartbeatFrequency(50, TimeUnit.MILLISECONDS)) .codecRegistry(fromRegistries( getDefaultCodecRegistry(), - fromProviders(PojoCodecProvider.builder().automatic(true).build()))) - .build()); - FailPoint ignored = FailPoint.enable(failPointDocument, primaryServerAddress)) { - MongoCollection coll = client.getDatabase(database.getName()) - .getCollection(collection.getNamespace().getCollectionName(), documentClass); - BsonValue insertedId = insertOperation.apply(client, coll); + fromProviders(PojoCodecProvider.builder().automatic(true).build())))); + FailPoint ignored = FailPoint.enable(failPointDocument, getPrimary())) { + MongoCollection collection = droppedCollection(client, documentClass); + BsonValue insertedId = insertOperation.apply(client, collection); if (expectIdGenerated) { assertNotNull(insertedId); } else { @@ -259,21 +252,22 @@ public void commandStarted(final CommandStartedEvent event) { } } - private void setFailPoint() { - failPointDocument = new BsonDocument("configureFailPoint", new BsonString("failCommand")) - .append("mode", new BsonDocument("times", new BsonInt32(1))) - .append("data", new BsonDocument("failCommands", new BsonArray(asList(new BsonString("insert")))) - .append("writeConcernError", new BsonDocument("code", new BsonInt32(100)) - .append("codeName", new BsonString("UnsatisfiableWriteConcern")) - .append("errmsg", new BsonString("Not enough data-bearing nodes")) - .append("errInfo", new BsonDocument("writeConcern", new BsonDocument("w", new BsonInt32(2)) - .append("wtimeout", new BsonInt32(0)) - .append("provenance", new BsonString("clientSupplied")))))); - getCollectionHelper().runAdminCommand(failPointDocument); + protected MongoClient createMongoClient(final MongoClientSettings.Builder mongoClientSettingsBuilder) { + return MongoClients.create(mongoClientSettingsBuilder.build()); + } + + private MongoCollection droppedCollection(final MongoClient client, final Class documentClass) { + return droppedDatabase(client).getCollection(namespace().getCollectionName(), documentClass); + } + + private MongoDatabase droppedDatabase(final MongoClient client) { + MongoDatabase database = client.getDatabase(namespace().getDatabaseName()); + database.drop(); + return database; } - private void disableFailPoint() { - getCollectionHelper().runAdminCommand(failPointDocument.append("mode", new BsonString("off"))); + private MongoNamespace namespace() { + return new MongoNamespace(getDefaultDatabaseName(), getClass().getSimpleName()); } public static final class MyDocument { From 70bb42248de2536f7d6e4160382230edacf3b3da Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Fri, 30 Aug 2024 11:02:03 -0600 Subject: [PATCH 35/59] Add methods for all prose tests. Where possible, implement them JAVA-5528 --- .../client/internal/MongoClusterImpl.java | 2 +- ...tClientSideOperationsTimeoutProseTest.java | 8 + .../com/mongodb/client/CrudProseTest.java | 153 ++++++++++++++++++ 3 files changed, 162 insertions(+), 1 deletion(-) diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index a36220a5a57..83abd7f3515 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -386,7 +386,7 @@ private ClientBulkWriteResult executeBulkWrite( @Nullable final ClientSession clientSession, final List clientWriteModels, @Nullable final ClientBulkWriteOptions options) { - isTrue("`autoEncryptionSettings` is null, as automatic encryption is not yet supported", autoEncryptionSettings == null); + isTrue("`autoEncryptionSettings` is null, as bulkWrite does not currently support automatic encryption", autoEncryptionSettings == null); return operationExecutor.execute(operations.clientBulkWriteOperation(clientWriteModels, options), readConcern, clientSession); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index 418f874aabe..b42bbb3c7a6 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -700,6 +700,14 @@ public void test10CustomTestWithTransactionUsesASingleTimeoutWithLock() { } } + @DisplayName("11. Multi-batch bulkWrites") + @Test + void test11MultiBatchBulkWrites() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/client-side-operations-timeout/tests/README.md#11-multi-batch-bulkwrites"); + } + /** * Not a prose spec test. However, it is additional test case for better coverage. */ diff --git a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java index 7a669cab097..5a9387c7e88 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java @@ -16,16 +16,21 @@ package com.mongodb.client; +import com.mongodb.AutoEncryptionSettings; import com.mongodb.MongoBulkWriteException; +import com.mongodb.MongoClientException; import com.mongodb.MongoClientSettings; import com.mongodb.MongoNamespace; import com.mongodb.MongoWriteConcernException; import com.mongodb.MongoWriteException; +import com.mongodb.WriteConcern; import com.mongodb.assertions.Assertions; import com.mongodb.client.model.CreateCollectionOptions; import com.mongodb.client.model.Filters; import com.mongodb.client.model.InsertOneModel; import com.mongodb.client.model.ValidationOptions; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; +import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.event.CommandListener; import com.mongodb.event.CommandStartedEvent; import org.bson.BsonArray; @@ -43,8 +48,11 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -55,6 +63,8 @@ import java.util.stream.Stream; import static com.mongodb.ClusterFixture.isDiscoverableReplicaSet; +import static com.mongodb.ClusterFixture.isServerlessTest; +import static com.mongodb.ClusterFixture.isStandalone; import static com.mongodb.ClusterFixture.serverVersionAtLeast; import static com.mongodb.MongoClientSettings.getDefaultCodecRegistry; import static com.mongodb.client.Fixture.getDefaultDatabaseName; @@ -62,7 +72,10 @@ import static com.mongodb.client.Fixture.getPrimary; import static com.mongodb.client.model.bulk.ClientBulkWriteOptions.clientBulkWriteOptions; import static com.mongodb.client.model.bulk.ClientNamespacedWriteModel.insertOne; +import static java.lang.String.join; +import static java.util.Collections.nCopies; import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; import static org.bson.codecs.configuration.CodecRegistries.fromProviders; import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; import static org.junit.jupiter.api.Assertions.assertAll; @@ -72,6 +85,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.params.provider.Arguments.arguments; @@ -143,6 +157,144 @@ void testWriteErrorDetailsIsPropagated() { } } + @DisplayName("3. MongoClient.bulkWrite batch splits a writeModels input with greater than maxWriteBatchSize operations") + @Test + void testBulkWriteSplitsWhenExceedingMaxWriteBatchSize() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.md#3-mongoclientbulkwrite-batch-splits-a-writemodels-input-with-greater-than-maxwritebatchsize-operations"); + } + + @DisplayName("4. MongoClient.bulkWrite batch splits when an ops payload exceeds maxMessageSizeBytes") + @Test + void testBulkWriteSplitsWhenExceedingMaxMessageSizeBytes() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.md#4-mongoclientbulkwrite-batch-splits-when-an-ops-payload-exceeds-maxmessagesizebytes"); + } + + @DisplayName("5. MongoClient.bulkWrite collects WriteConcernErrors across batches") + @Test + void testBulkWriteCollectsWriteConcernErrorsAcrossBatches() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.md#5-mongoclientbulkwrite-collects-writeconcernerrors-across-batches"); + } + + @DisplayName("6. MongoClient.bulkWrite handles individual WriteErrors across batches") + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void testBulkWriteHandlesWriteErrorsAcrossBatches(final boolean ordered) { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.md#6-mongoclientbulkwrite-handles-individual-writeerrors-across-batches"); + } + + @DisplayName("7. MongoClient.bulkWrite handles a cursor requiring a getMore") + @Test + void testBulkWriteHandlesCursorRequiringGetMore() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeFalse(isStandalone()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement batch splitting https://jira.mongodb.org/browse/JAVA-5529"); + ArrayList startedBulkWriteCommandEvents = new ArrayList<>(); + CommandListener commandListener = new CommandListener() { + @Override + public void commandStarted(final CommandStartedEvent event) { + if (event.getCommandName().equals("bulkWrite")) { + startedBulkWriteCommandEvents.add(event); + } + } + }; + try (MongoClient client = createMongoClient(getMongoClientSettingsBuilder().addCommandListener(commandListener))) { + int maxWriteBatchSize = droppedDatabase(client).runCommand(new Document("hello", 1)).getInteger("maxWriteBatchSize"); + ClientBulkWriteResult result = client.bulkWrite(nCopies( + maxWriteBatchSize + 1, + ClientNamespacedWriteModel.insertOne(namespace(), new Document("a", "b")))); + assertEquals(maxWriteBatchSize + 1, result.getInsertedCount()); + assertEquals(2, startedBulkWriteCommandEvents.size()); + CommandStartedEvent firstEvent = startedBulkWriteCommandEvents.get(0); + CommandStartedEvent secondEvent = startedBulkWriteCommandEvents.get(1); + assertEquals(maxWriteBatchSize, firstEvent.getCommand().getArray("ops").size()); + assertEquals(1, secondEvent.getCommand().getArray("ops").size()); + assertEquals(firstEvent.getOperationId(), secondEvent.getOperationId()); + } + } + + @DisplayName("8. MongoClient.bulkWrite handles a cursor requiring getMore within a transaction") + @Test + void testBulkWriteHandlesCursorRequiringGetMoreWithinTransaction() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.md#8-mongoclientbulkwrite-handles-a-cursor-requiring-getmore-within-a-transaction"); + } + + @DisplayName("10. MongoClient.bulkWrite returns error for unacknowledged too-large insert") + @ParameterizedTest + @ValueSource(strings = {"insert", "replace"}) + void testBulkWriteErrorsForUnacknowledgedTooLargeInsert(final String operationType) { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement maxBsonObjectSize validation https://jira.mongodb.org/browse/JAVA-5529"); + try (MongoClient client = createMongoClient(getMongoClientSettingsBuilder() + .writeConcern(WriteConcern.ACKNOWLEDGED))) { + int maxBsonObjectSize = droppedDatabase(client).runCommand(new Document("hello", 1)).getInteger("maxBsonObjectSize"); + Document document = new Document("a", join("", nCopies(maxBsonObjectSize, "b"))); + ClientNamespacedWriteModel model; + switch (operationType) { + case "insert": { + model = ClientNamespacedWriteModel.insertOne(namespace(), document); + break; + } + case "replace": { + model = ClientNamespacedWriteModel.replaceOne(namespace(), Filters.empty(), document); + break; + } + default: { + throw Assertions.fail(operationType); + } + } + assertThrows(MongoClientException.class, () -> client.bulkWrite(singletonList(model))); + } + } + + @DisplayName("11. MongoClient.bulkWrite batch splits when the addition of a new namespace exceeds the maximum message size") + @Test + void testBulkWriteSplitsWhenExceedingMaxMessageSizeBytesDueToNsInfo() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.md#11-mongoclientbulkwrite-batch-splits-when-the-addition-of-a-new-namespace-exceeds-the-maximum-message-size"); + } + + @DisplayName("12. MongoClient.bulkWrite returns an error if no operations can be added to ops") + @Test + void testBulkWriteSplitsErrorsForTooLargeOpsOrNsInfo() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + assumeTrue(Runtime.getRuntime().availableProcessors() < 1, "BULK-TODO implement prose test https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.md#12-mongoclientbulkwrite-returns-an-error-if-no-operations-can-be-added-to-ops"); + } + + @DisplayName("13. MongoClient.bulkWrite returns an error if auto-encryption is configured") + @Test + void testBulkWriteErrorsForAutoEncryption() { + assumeTrue(serverVersionAtLeast(8, 0)); + assumeFalse(isServerlessTest()); + HashMap awsKmsProviderProperties = new HashMap<>(); + awsKmsProviderProperties.put("accessKeyId", "foo"); + awsKmsProviderProperties.put("secretAccessKey", "bar"); + try (MongoClient client = createMongoClient(getMongoClientSettingsBuilder() + .autoEncryptionSettings(AutoEncryptionSettings.builder() + .keyVaultNamespace(namespace().getFullName()) + .kmsProviders(singletonMap("aws", awsKmsProviderProperties)) + .build()))) { + assertTrue( + assertThrows( + IllegalStateException.class, + () -> client.bulkWrite(singletonList(ClientNamespacedWriteModel.insertOne(namespace(), new Document("a", "b"))))) + .getMessage().contains("bulkWrite does not currently support automatic encryption")); + } + } + /** * This test is not from the specification. */ @@ -152,6 +304,7 @@ void insertMustGenerateIdAtMostOnce( final Class documentClass, final boolean expectIdGenerated, final Supplier documentSupplier) { + assumeTrue(serverVersionAtLeast(8, 0)); assumeTrue(isDiscoverableReplicaSet()); assertAll( () -> assertInsertMustGenerateIdAtMostOnce("insert", documentClass, expectIdGenerated, From 3584de5c72b0cf067574146dd36f93712f24f4be Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Fri, 30 Aug 2024 11:18:32 -0600 Subject: [PATCH 36/59] Move results to `com.mongodb.client.model.bulk` JAVA-5527 --- .../com/mongodb/ClientBulkWriteException.java | 2 +- .../model/bulk/ClientBulkWriteOptions.java | 1 - .../bulk/ClientBulkWriteResult.java | 4 +--- .../bulk/ClientDeleteResult.java | 3 +-- .../bulk/ClientInsertOneResult.java | 3 +-- .../bulk/ClientUpdateResult.java | 3 +-- .../client/model/bulk/package-info.java | 2 +- .../client/result/bulk/package-info.java | 23 ------------------- ...nowledgedSummaryClientBulkWriteResult.java | 2 +- ...nowledgedVerboseClientBulkWriteResult.java | 8 +++---- .../bulk/ConcreteClientDeleteResult.java | 2 +- .../bulk/ConcreteClientInsertOneResult.java | 2 +- .../bulk/ConcreteClientUpdateResult.java | 2 +- .../UnacknowledgedClientBulkWriteResult.java | 2 +- .../coroutine/syncadapter/SyncMongoCluster.kt | 2 +- .../client/syncadapter/SyncMongoCluster.kt | 2 +- .../client/syncadapter/SyncMongoClient.java | 2 +- .../client/syncadapter/SyncMongoCluster.java | 2 +- .../scala/syncadapter/SyncMongoCluster.scala | 3 +-- .../main/com/mongodb/client/MongoCluster.java | 2 +- .../client/internal/MongoClientImpl.java | 2 +- .../client/internal/MongoClusterImpl.java | 2 +- 22 files changed, 23 insertions(+), 53 deletions(-) rename driver-core/src/main/com/mongodb/client/{result => model}/bulk/ClientBulkWriteResult.java (97%) rename driver-core/src/main/com/mongodb/client/{result => model}/bulk/ClientDeleteResult.java (92%) rename driver-core/src/main/com/mongodb/client/{result => model}/bulk/ClientInsertOneResult.java (94%) rename driver-core/src/main/com/mongodb/client/{result => model}/bulk/ClientUpdateResult.java (94%) delete mode 100644 driver-core/src/main/com/mongodb/client/result/bulk/package-info.java diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index 6e9af782b0c..a2874dc1c38 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -17,7 +17,7 @@ import com.mongodb.bulk.WriteConcernError; import com.mongodb.client.model.bulk.ClientWriteModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.lang.Nullable; import java.util.List; diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java index e3e19d44041..138f8678477 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java @@ -17,7 +17,6 @@ import com.mongodb.annotations.Sealed; import com.mongodb.client.model.Filters; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; import com.mongodb.internal.client.model.bulk.ConcreteClientBulkWriteOptions; import com.mongodb.lang.Nullable; import org.bson.BsonValue; diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java similarity index 97% rename from driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java index 5b49f7e4586..1b02cd2f6b7 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java @@ -13,14 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.client.result.bulk; +package com.mongodb.client.model.bulk; import com.mongodb.ClientBulkWriteException; import com.mongodb.WriteConcern; import com.mongodb.annotations.Evolving; import com.mongodb.bulk.WriteConcernError; -import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientWriteModel; import java.util.Map; import java.util.Optional; diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientDeleteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java similarity index 92% rename from driver-core/src/main/com/mongodb/client/result/bulk/ClientDeleteResult.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java index 8ac49725dbf..6da68c0c1c9 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientDeleteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.client.result.bulk; +package com.mongodb.client.model.bulk; import com.mongodb.annotations.Evolving; import com.mongodb.bulk.WriteConcernError; -import com.mongodb.client.model.bulk.ClientWriteModel; /** * The result of a successful {@linkplain ClientWriteModel individual delete operation}. diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java similarity index 94% rename from driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java index 60ea4581ac0..598b149db92 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.client.result.bulk; +package com.mongodb.client.model.bulk; import com.mongodb.annotations.Evolving; import com.mongodb.bulk.WriteConcernError; -import com.mongodb.client.model.bulk.ClientWriteModel; import org.bson.BsonValue; import org.bson.RawBsonDocument; diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/ClientUpdateResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java similarity index 94% rename from driver-core/src/main/com/mongodb/client/result/bulk/ClientUpdateResult.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java index af5e2e26fa8..1392b7ec0c7 100644 --- a/driver-core/src/main/com/mongodb/client/result/bulk/ClientUpdateResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.client.result.bulk; +package com.mongodb.client.model.bulk; import com.mongodb.annotations.Evolving; import com.mongodb.bulk.WriteConcernError; -import com.mongodb.client.model.bulk.ClientWriteModel; import org.bson.BsonValue; import java.util.Optional; diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/package-info.java b/driver-core/src/main/com/mongodb/client/model/bulk/package-info.java index 309c0e4cfa6..b9cb98f41a7 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/package-info.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/package-info.java @@ -15,7 +15,7 @@ */ /** - * Models and options for the client-level bulk write operation. + * Models, options, results for the client-level bulk write operation. */ @NonNullApi package com.mongodb.client.model.bulk; diff --git a/driver-core/src/main/com/mongodb/client/result/bulk/package-info.java b/driver-core/src/main/com/mongodb/client/result/bulk/package-info.java deleted file mode 100644 index 744a2f1c055..00000000000 --- a/driver-core/src/main/com/mongodb/client/result/bulk/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Results of the client-level bulk write operation. - */ -@NonNullApi -package com.mongodb.client.result.bulk; - -import com.mongodb.lang.NonNullApi; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java index 4f55be5e01b..5137314f911 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java @@ -15,7 +15,7 @@ */ package com.mongodb.internal.client.result.bulk; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import java.util.Objects; import java.util.Optional; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java index dbd3ab65414..38ceee32ed9 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -15,10 +15,10 @@ */ package com.mongodb.internal.client.result.bulk; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; -import com.mongodb.client.result.bulk.ClientDeleteResult; -import com.mongodb.client.result.bulk.ClientInsertOneResult; -import com.mongodb.client.result.bulk.ClientUpdateResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientDeleteResult; +import com.mongodb.client.model.bulk.ClientInsertOneResult; +import com.mongodb.client.model.bulk.ClientUpdateResult; import java.util.Map; import java.util.Objects; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java index e94b442d390..f7ae65cbf92 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java @@ -15,7 +15,7 @@ */ package com.mongodb.internal.client.result.bulk; -import com.mongodb.client.result.bulk.ClientDeleteResult; +import com.mongodb.client.model.bulk.ClientDeleteResult; /** * This class is not part of the public API and may be removed or changed at any time. diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java index 7cb439388e1..74e04851849 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java @@ -15,7 +15,7 @@ */ package com.mongodb.internal.client.result.bulk; -import com.mongodb.client.result.bulk.ClientInsertOneResult; +import com.mongodb.client.model.bulk.ClientInsertOneResult; import com.mongodb.lang.Nullable; import org.bson.BsonValue; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java index 7b3e8b36e9d..62b3e6dfc3d 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java @@ -15,7 +15,7 @@ */ package com.mongodb.internal.client.result.bulk; -import com.mongodb.client.result.bulk.ClientUpdateResult; +import com.mongodb.client.model.bulk.ClientUpdateResult; import com.mongodb.lang.Nullable; import org.bson.BsonValue; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java index 7288b4be333..77f73338a93 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java @@ -16,7 +16,7 @@ package com.mongodb.internal.client.result.bulk; import com.mongodb.annotations.Immutable; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import java.util.Optional; diff --git a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt index e19f198e6d5..a3f4eada2a0 100644 --- a/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncMongoCluster.kt @@ -26,8 +26,8 @@ import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable import com.mongodb.client.model.bulk.ClientBulkWriteOptions +import com.mongodb.client.model.bulk.ClientBulkWriteResult import com.mongodb.client.model.bulk.ClientNamespacedWriteModel -import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.coroutine.MongoCluster import java.util.concurrent.TimeUnit import kotlinx.coroutines.runBlocking diff --git a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt index 24411058ff3..55cc156d0a3 100644 --- a/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt +++ b/driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncMongoCluster.kt @@ -26,8 +26,8 @@ import com.mongodb.client.MongoCluster as JMongoCluster import com.mongodb.client.MongoDatabase import com.mongodb.client.MongoIterable import com.mongodb.client.model.bulk.ClientBulkWriteOptions +import com.mongodb.client.model.bulk.ClientBulkWriteResult import com.mongodb.client.model.bulk.ClientNamespacedWriteModel -import com.mongodb.client.result.bulk.ClientBulkWriteResult import com.mongodb.kotlin.client.MongoCluster import java.util.concurrent.TimeUnit import org.bson.Document diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java index 311297aec45..3f2265cb795 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoClient.java @@ -30,7 +30,7 @@ import com.mongodb.client.MongoIterable; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.reactivestreams.client.internal.BatchCursor; import org.bson.Document; diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java index ec414b65160..19e58f829b0 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncMongoCluster.java @@ -30,7 +30,7 @@ import com.mongodb.client.MongoIterable; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import org.bson.BsonDocument; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; diff --git a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala index 26ccbd65900..15f4be00d0d 100644 --- a/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala +++ b/driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala @@ -1,8 +1,7 @@ package org.mongodb.scala.syncadapter import com.mongodb.assertions.Assertions -import com.mongodb.client.model.bulk.{ ClientBulkWriteOptions, ClientNamespacedWriteModel } -import com.mongodb.client.result.bulk.ClientBulkWriteResult +import com.mongodb.client.model.bulk.{ ClientBulkWriteOptions, ClientBulkWriteResult, ClientNamespacedWriteModel } import com.mongodb.{ ClientSessionOptions, ReadConcern, ReadPreference, WriteConcern } import com.mongodb.client.{ ClientSession, MongoCluster => JMongoCluster, MongoDatabase => JMongoDatabase } import org.bson.Document diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index c93b1a7299e..e1425ee5966 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -31,7 +31,7 @@ import com.mongodb.client.model.bulk.ClientDeleteManyModel; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.bulk.ClientUpdateManyModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.lang.Nullable; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java index 894005467e1..e15ecbb406a 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java @@ -34,7 +34,7 @@ import com.mongodb.client.SynchronousContextProvider; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.connection.ClusterDescription; import com.mongodb.connection.SocketSettings; import com.mongodb.connection.TransportSettings; diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java index 5b33898969e..d6eded9cda6 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java +++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java @@ -41,7 +41,7 @@ import com.mongodb.client.SynchronousContextProvider; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.internal.IgnorableRequestContext; import com.mongodb.internal.TimeoutSettings; import com.mongodb.internal.binding.ClusterAwareReadWriteBinding; From 8e1d7704742475cb672c5f49bfb2ffb0e80b007d Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Fri, 30 Aug 2024 11:32:02 -0600 Subject: [PATCH 37/59] Move internal results to `com.mongodb.internal.client.model.bulk` JAVA-5527 --- ...nowledgedSummaryClientBulkWriteResult.java | 2 +- ...nowledgedVerboseClientBulkWriteResult.java | 2 +- .../bulk/ConcreteClientDeleteResult.java | 2 +- .../bulk/ConcreteClientInsertOneResult.java | 2 +- .../bulk/ConcreteClientUpdateResult.java | 2 +- .../UnacknowledgedClientBulkWriteResult.java | 2 +- .../client/result/bulk/package-info.java | 23 ------------------- 7 files changed, 6 insertions(+), 29 deletions(-) rename driver-core/src/main/com/mongodb/internal/client/{result => model}/bulk/AcknowledgedSummaryClientBulkWriteResult.java (98%) rename driver-core/src/main/com/mongodb/internal/client/{result => model}/bulk/AcknowledgedVerboseClientBulkWriteResult.java (99%) rename driver-core/src/main/com/mongodb/internal/client/{result => model}/bulk/ConcreteClientDeleteResult.java (97%) rename driver-core/src/main/com/mongodb/internal/client/{result => model}/bulk/ConcreteClientInsertOneResult.java (97%) rename driver-core/src/main/com/mongodb/internal/client/{result => model}/bulk/ConcreteClientUpdateResult.java (98%) rename driver-core/src/main/com/mongodb/internal/client/{result => model}/bulk/UnacknowledgedClientBulkWriteResult.java (97%) delete mode 100644 driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java similarity index 98% rename from driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java index 5137314f911..bc72aaae52b 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedSummaryClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.internal.client.result.bulk; +package com.mongodb.internal.client.model.bulk; import com.mongodb.client.model.bulk.ClientBulkWriteResult; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java similarity index 99% rename from driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java index 38ceee32ed9..79e13b6478c 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.internal.client.result.bulk; +package com.mongodb.internal.client.model.bulk; import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.client.model.bulk.ClientDeleteResult; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteResult.java similarity index 97% rename from driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteResult.java index f7ae65cbf92..a82b8ee8b62 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientDeleteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.internal.client.result.bulk; +package com.mongodb.internal.client.model.bulk; import com.mongodb.client.model.bulk.ClientDeleteResult; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneResult.java similarity index 97% rename from driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneResult.java index 74e04851849..cc755e2c62d 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.internal.client.result.bulk; +package com.mongodb.internal.client.model.bulk; import com.mongodb.client.model.bulk.ClientInsertOneResult; import com.mongodb.lang.Nullable; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateResult.java similarity index 98% rename from driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateResult.java index 62b3e6dfc3d..54075b792f1 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/ConcreteClientUpdateResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.internal.client.result.bulk; +package com.mongodb.internal.client.model.bulk; import com.mongodb.client.model.bulk.ClientUpdateResult; import com.mongodb.lang.Nullable; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java similarity index 97% rename from driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java index 77f73338a93..167385be1fc 100644 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/UnacknowledgedClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.internal.client.result.bulk; +package com.mongodb.internal.client.model.bulk; import com.mongodb.annotations.Immutable; import com.mongodb.client.model.bulk.ClientBulkWriteResult; diff --git a/driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java b/driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java deleted file mode 100644 index d3dfae86619..00000000000 --- a/driver-core/src/main/com/mongodb/internal/client/result/bulk/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Internal program elements related to {@link com.mongodb.client.result.bulk}. - */ -@NonNullApi -package com.mongodb.internal.client.result.bulk; - -import com.mongodb.lang.NonNullApi; From e973615378c53aac7e12cc3d681d004cdc88f5ab Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Fri, 30 Aug 2024 11:43:37 -0600 Subject: [PATCH 38/59] Document that `bulkWrite` is not supported by serverless instances JAVA-5527 --- driver-sync/src/main/com/mongodb/client/MongoCluster.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index e1425ee5966..264ea22d4ac 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -371,6 +371,8 @@ public interface MongoCluster { * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + *

      + * This operation is not supported by MongoDB Atlas Serverless instances.

      * * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. * @return The {@link ClientBulkWriteResult} if the operation is successful. @@ -393,6 +395,8 @@ public interface MongoCluster { * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + *

      + * This operation is not supported by MongoDB Atlas Serverless instances.

      * * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. * @param options The options. @@ -420,6 +424,8 @@ ClientBulkWriteResult bulkWrite( * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + *

      + * This operation is not supported by MongoDB Atlas Serverless instances.

      * * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. @@ -445,6 +451,8 @@ ClientBulkWriteResult bulkWrite( * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + *

      + * This operation is not supported by MongoDB Atlas Serverless instances.

      * * @param clientSession The {@linkplain ClientSession client session} with which to associate this operation. * @param models The {@linkplain ClientNamespacedWriteModel individual write operations}. From ee893f27d6da29a80590f7a91d26b07bf50db251 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Fri, 30 Aug 2024 11:55:37 -0600 Subject: [PATCH 39/59] Fixes after the merge JAVA-5528 --- .../operation/ClientBulkWriteOperation.java | 20 +++++++++---------- .../internal/operation/SyncOperations.java | 2 +- .../com/mongodb/client/CrudProseTest.java | 2 +- .../client/unified/UnifiedCrudHelper.java | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index 6ec3c838576..a00524ebdcd 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -39,10 +39,10 @@ import com.mongodb.client.model.bulk.ClientUpdateOneModel; import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; -import com.mongodb.client.result.bulk.ClientDeleteResult; -import com.mongodb.client.result.bulk.ClientInsertOneResult; -import com.mongodb.client.result.bulk.ClientUpdateResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientDeleteResult; +import com.mongodb.client.model.bulk.ClientInsertOneResult; +import com.mongodb.client.model.bulk.ClientUpdateResult; import com.mongodb.connection.ConnectionDescription; import com.mongodb.internal.TimeoutContext; import com.mongodb.internal.async.function.RetryState; @@ -59,12 +59,12 @@ import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOptions; import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedWriteModel; -import com.mongodb.internal.client.result.bulk.AcknowledgedSummaryClientBulkWriteResult; -import com.mongodb.internal.client.result.bulk.AcknowledgedVerboseClientBulkWriteResult; -import com.mongodb.internal.client.result.bulk.ConcreteClientDeleteResult; -import com.mongodb.internal.client.result.bulk.ConcreteClientInsertOneResult; -import com.mongodb.internal.client.result.bulk.ConcreteClientUpdateResult; -import com.mongodb.internal.client.result.bulk.UnacknowledgedClientBulkWriteResult; +import com.mongodb.internal.client.model.bulk.AcknowledgedSummaryClientBulkWriteResult; +import com.mongodb.internal.client.model.bulk.AcknowledgedVerboseClientBulkWriteResult; +import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteResult; +import com.mongodb.internal.client.model.bulk.ConcreteClientInsertOneResult; +import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateResult; +import com.mongodb.internal.client.model.bulk.UnacknowledgedClientBulkWriteResult; import com.mongodb.internal.connection.Connection; import com.mongodb.internal.connection.IdHoldingBsonWriter; import com.mongodb.internal.connection.MongoWriteConcernWithResponseException; diff --git a/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java b/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java index 9680a23c9b1..65a6a9fe82e 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java +++ b/driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java @@ -48,7 +48,7 @@ import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocumentBeforeChange; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.internal.TimeoutSettings; import com.mongodb.internal.client.model.AggregationLevel; import com.mongodb.internal.client.model.FindOptions; diff --git a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java index 5a9387c7e88..67790699f42 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java @@ -30,7 +30,7 @@ import com.mongodb.client.model.InsertOneModel; import com.mongodb.client.model.ValidationOptions; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.event.CommandListener; import com.mongodb.event.CommandStartedEvent; import org.bson.BsonArray; diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index 7fc5d1de6d6..e8e427d0a04 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -88,8 +88,8 @@ import com.mongodb.client.result.InsertManyResult; import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.UpdateResult; -import com.mongodb.client.result.bulk.ClientBulkWriteResult; -import com.mongodb.client.result.bulk.ClientUpdateResult; +import com.mongodb.client.model.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientUpdateResult; import com.mongodb.lang.NonNull; import com.mongodb.lang.Nullable; import org.bson.BsonArray; From e33f592ace96d19d0a4484e3607bdd6d67f9d959 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 3 Sep 2024 13:12:42 -0600 Subject: [PATCH 40/59] Add subtypes of `ClientNamespacedWriteModel` and hide `ClientWriteModel` JAVA-5527 --- .../com/mongodb/ClientBulkWriteException.java | 6 +- .../model/bulk/ClientBulkWriteOptions.java | 4 +- .../model/bulk/ClientBulkWriteResult.java | 8 +-- .../client/model/bulk/ClientDeleteResult.java | 2 +- .../model/bulk/ClientInsertOneResult.java | 2 +- ...a => ClientNamespacedDeleteManyModel.java} | 2 +- ...va => ClientNamespacedDeleteOneModel.java} | 2 +- ...va => ClientNamespacedInsertOneModel.java} | 2 +- ...a => ClientNamespacedReplaceOneModel.java} | 2 +- ...a => ClientNamespacedUpdateManyModel.java} | 2 +- ...va => ClientNamespacedUpdateOneModel.java} | 2 +- .../bulk/ClientNamespacedWriteModel.java | 64 ++++++++++--------- .../client/model/bulk/ClientUpdateResult.java | 2 +- .../client/model/bulk/ClientWriteModel.java | 9 +-- .../bulk/ConcreteClientDeleteManyModel.java | 3 +- .../bulk/ConcreteClientDeleteOneModel.java | 3 +- .../bulk/ConcreteClientInsertOneModel.java | 4 +- .../ConcreteClientNamespacedWriteModel.java | 18 ++++-- .../bulk/ConcreteClientReplaceOneModel.java | 3 +- .../bulk/ConcreteClientUpdateManyModel.java | 3 +- .../bulk/ConcreteClientUpdateOneModel.java | 3 +- .../main/com/mongodb/client/MongoCluster.java | 12 ++-- 22 files changed, 80 insertions(+), 78 deletions(-) rename driver-core/src/main/com/mongodb/client/model/bulk/{ClientDeleteManyModel.java => ClientNamespacedDeleteManyModel.java} (90%) rename driver-core/src/main/com/mongodb/client/model/bulk/{ClientDeleteOneModel.java => ClientNamespacedDeleteOneModel.java} (90%) rename driver-core/src/main/com/mongodb/client/model/bulk/{ClientInsertOneModel.java => ClientNamespacedInsertOneModel.java} (89%) rename driver-core/src/main/com/mongodb/client/model/bulk/{ClientReplaceOneModel.java => ClientNamespacedReplaceOneModel.java} (90%) rename driver-core/src/main/com/mongodb/client/model/bulk/{ClientUpdateManyModel.java => ClientNamespacedUpdateManyModel.java} (90%) rename driver-core/src/main/com/mongodb/client/model/bulk/{ClientUpdateOneModel.java => ClientNamespacedUpdateOneModel.java} (90%) rename driver-core/src/main/com/mongodb/{ => internal}/client/model/bulk/ClientWriteModel.java (83%) diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index a2874dc1c38..04641b36173 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -16,8 +16,8 @@ package com.mongodb; import com.mongodb.bulk.WriteConcernError; -import com.mongodb.client.model.bulk.ClientWriteModel; import com.mongodb.client.model.bulk.ClientBulkWriteResult; +import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.lang.Nullable; import java.util.List; @@ -112,7 +112,7 @@ public List getWriteConcernErrors() { /** * The indexed {@link WriteError}s. - * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientNamespacedWriteModel}s * in the corresponding client-level bulk write operation. *

      * There are no guarantees on mutability or iteration order of the {@link Map} returned.

      @@ -130,7 +130,7 @@ public Map getWriteErrors() { * The result of the successful part of a client-level bulk write operation. * * @return The successful partial result. {@linkplain Optional#isPresent() Present} only if at least one - * {@linkplain ClientWriteModel individual write operation} succeed. + * {@linkplain ClientNamespacedWriteModel individual write operation} succeed. */ public Optional getPartialResult() { return ofNullable(partialResult); diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java index 138f8678477..10142f8aa15 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java @@ -39,7 +39,7 @@ static ClientBulkWriteOptions clientBulkWriteOptions() { } /** - * Enables or disables ordered execution of {@linkplain ClientWriteModel individual write operations}. + * Enables or disables ordered execution of {@linkplain ClientNamespacedWriteModel individual write operations}. * In an ordered execution a failure of an individual operation prevents the rest of them * from being executed. * In an unordered execution failures of individual operations do not prevent the rest of them @@ -60,7 +60,7 @@ static ClientBulkWriteOptions clientBulkWriteOptions() { ClientBulkWriteOptions bypassDocumentValidation(@Nullable Boolean bypassDocumentValidation); /** - * Sets variables that can be referenced from {@linkplain ClientWriteModel individual write operations} + * Sets variables that can be referenced from {@linkplain ClientNamespacedWriteModel individual write operations} * with the {@code "$$"} syntax, which in turn requires using {@link Filters#expr(Object)} when specifying filters. * Values must be constants or expressions that do not reference fields. * diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java index 1b02cd2f6b7..c9a7cf4b403 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java @@ -25,7 +25,7 @@ /** * The result of a successful or partially successful client-level bulk write operation. - * Note that if only some of the {@linkplain ClientWriteModel individual write operations} succeed, + * Note that if only some of the {@linkplain ClientNamespacedWriteModel individual write operations} succeed, * or if there are {@link WriteConcernError}s, then the successful partial result * is still accessible via {@link ClientBulkWriteException#getPartialResult()}. * @@ -100,7 +100,7 @@ public interface ClientBulkWriteResult { interface Verbose { /** * The indexed {@link ClientInsertOneResult}s. - * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientNamespacedWriteModel}s * in the client-level bulk write operation. *

      * There are no guarantees on mutability or iteration order of the {@link Map} returned.

      @@ -112,7 +112,7 @@ interface Verbose { /** * The indexed {@link ClientUpdateResult}s. - * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientNamespacedWriteModel}s * in the client-level bulk write operation. *

      * There are no guarantees on mutability or iteration order of the {@link Map} returned.

      @@ -124,7 +124,7 @@ interface Verbose { /** * The indexed {@link ClientDeleteResult}s. - * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientWriteModel}s + * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientNamespacedWriteModel}s * in the client-level bulk write operation. *

      * There are no guarantees on mutability or iteration order of the {@link Map} returned.

      diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java index 6da68c0c1c9..0ac0dcd8ab1 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java @@ -19,7 +19,7 @@ import com.mongodb.bulk.WriteConcernError; /** - * The result of a successful {@linkplain ClientWriteModel individual delete operation}. + * The result of a successful {@linkplain ClientNamespacedWriteModel individual delete operation}. * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. * * @since 5.3 diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java index 598b149db92..aa7641ed233 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java @@ -23,7 +23,7 @@ import java.util.Optional; /** - * The result of a successful {@linkplain ClientWriteModel individual insert one operation}. + * The result of a successful {@linkplain ClientNamespacedWriteModel individual insert one operation}. * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. * * @since 5.3 diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedDeleteManyModel.java similarity index 90% rename from driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedDeleteManyModel.java index aba7af9d732..a4e445e5e86 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedDeleteManyModel.java @@ -24,5 +24,5 @@ * @since 5.3 */ @Sealed -public interface ClientDeleteManyModel extends ClientWriteModel { +public interface ClientNamespacedDeleteManyModel extends ClientNamespacedWriteModel { } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedDeleteOneModel.java similarity index 90% rename from driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedDeleteOneModel.java index c88c4d2ac12..0ba508007a6 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedDeleteOneModel.java @@ -24,5 +24,5 @@ * @since 5.3 */ @Sealed -public interface ClientDeleteOneModel extends ClientWriteModel { +public interface ClientNamespacedDeleteOneModel extends ClientNamespacedWriteModel { } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedInsertOneModel.java similarity index 89% rename from driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneModel.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedInsertOneModel.java index 7237490a133..66d9f39c74d 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedInsertOneModel.java @@ -24,5 +24,5 @@ * @since 5.3 */ @Sealed -public interface ClientInsertOneModel extends ClientWriteModel { +public interface ClientNamespacedInsertOneModel extends ClientNamespacedWriteModel { } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedReplaceOneModel.java similarity index 90% rename from driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOneModel.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedReplaceOneModel.java index c3467266cc1..a4edf9b716a 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedReplaceOneModel.java @@ -24,5 +24,5 @@ * @since 5.3 */ @Sealed -public interface ClientReplaceOneModel extends ClientWriteModel { +public interface ClientNamespacedReplaceOneModel extends ClientNamespacedWriteModel { } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedUpdateManyModel.java similarity index 90% rename from driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateManyModel.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedUpdateManyModel.java index 459cde6fcd2..3900c8779f7 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedUpdateManyModel.java @@ -24,5 +24,5 @@ * @since 5.3 */ @Sealed -public interface ClientUpdateManyModel extends ClientWriteModel { +public interface ClientNamespacedUpdateManyModel extends ClientNamespacedWriteModel { } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedUpdateOneModel.java similarity index 90% rename from driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOneModel.java rename to driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedUpdateOneModel.java index ad5255b53eb..3d9e785004f 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedUpdateOneModel.java @@ -24,5 +24,5 @@ * @since 5.3 */ @Sealed -public interface ClientUpdateOneModel extends ClientWriteModel { +public interface ClientNamespacedUpdateOneModel extends ClientNamespacedWriteModel { } diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java index 82d522780ba..388113530c7 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java @@ -34,7 +34,7 @@ import static com.mongodb.assertions.Assertions.notNull; /** - * A combination of an {@linkplain ClientWriteModel individual write operation} and a {@linkplain MongoNamespace namespace} + * A combination of an individual write operation and a {@linkplain MongoNamespace namespace} * the operation is targeted at. * * @since 5.3 @@ -46,11 +46,11 @@ public interface ClientNamespacedWriteModel { * * @param namespace The namespace. * @param document The document. - * @return The requested {@link ClientInsertOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedInsertOneModel}. * @param The document type, for example {@link Document}. * @see Filters */ - static ClientNamespacedWriteModel insertOne(final MongoNamespace namespace, final TDocument document) { + static ClientNamespacedInsertOneModel insertOne(final MongoNamespace namespace, final TDocument document) { notNull("namespace", namespace); notNull("document", document); return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientInsertOneModel(document)); @@ -64,11 +64,11 @@ static ClientNamespacedWriteModel insertOne(final MongoNamespace nam * @param namespace The namespace. * @param filter The filter. * @param update The update. - * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateOneModel}. * @see Filters * @see Updates */ - static ClientNamespacedWriteModel updateOne(final MongoNamespace namespace, final Bson filter, final Bson update) { + static ClientNamespacedUpdateOneModel updateOne(final MongoNamespace namespace, final Bson filter, final Bson update) { notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); @@ -82,11 +82,11 @@ static ClientNamespacedWriteModel updateOne(final MongoNamespace namespace, fina * @param filter The filter. * @param update The update. * @param options The options. - * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateOneModel}. * @see Filters * @see Updates */ - static ClientNamespacedWriteModel updateOne( + static ClientNamespacedUpdateOneModel updateOne( final MongoNamespace namespace, final Bson filter, final Bson update, final ClientUpdateOptions options) { notNull("namespace", namespace); notNull("filter", filter); @@ -103,11 +103,12 @@ static ClientNamespacedWriteModel updateOne( * @param namespace The namespace. * @param filter The filter. * @param updatePipeline The update pipeline. - * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateOneModel}. * @see Filters * @see Aggregates */ - static ClientNamespacedWriteModel updateOne(final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { + static ClientNamespacedUpdateOneModel updateOne( + final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); @@ -121,11 +122,11 @@ static ClientNamespacedWriteModel updateOne(final MongoNamespace namespace, fina * @param filter The filter. * @param updatePipeline The update pipeline. * @param options The options. - * @return The requested {@link ClientUpdateOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateOneModel}. * @see Filters * @see Aggregates */ - static ClientNamespacedWriteModel updateOne( + static ClientNamespacedUpdateOneModel updateOne( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { notNull("namespace", namespace); notNull("filter", filter); @@ -142,11 +143,11 @@ static ClientNamespacedWriteModel updateOne( * @param namespace The namespace. * @param filter The filter. * @param update The update. - * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateManyModel}. * @see Filters * @see Updates */ - static ClientNamespacedWriteModel updateMany(final MongoNamespace namespace, final Bson filter, final Bson update) { + static ClientNamespacedUpdateManyModel updateMany(final MongoNamespace namespace, final Bson filter, final Bson update) { notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); @@ -160,11 +161,11 @@ static ClientNamespacedWriteModel updateMany(final MongoNamespace namespace, fin * @param filter The filter. * @param update The update. * @param options The options. - * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateManyModel}. * @see Filters * @see Updates */ - static ClientNamespacedWriteModel updateMany( + static ClientNamespacedUpdateManyModel updateMany( final MongoNamespace namespace, final Bson filter, final Bson update, final ClientUpdateOptions options) { notNull("namespace", namespace); notNull("filter", filter); @@ -181,11 +182,12 @@ static ClientNamespacedWriteModel updateMany( * @param namespace The namespace. * @param filter The filter. * @param updatePipeline The update pipeline. - * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateManyModel}. * @see Filters * @see Aggregates */ - static ClientNamespacedWriteModel updateMany(final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { + static ClientNamespacedUpdateManyModel updateMany( + final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline) { notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); @@ -199,11 +201,11 @@ static ClientNamespacedWriteModel updateMany(final MongoNamespace namespace, fin * @param filter The filter. * @param updatePipeline The update pipeline. * @param options The options. - * @return The requested {@link ClientUpdateManyModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedUpdateManyModel}. * @see Filters * @see Aggregates */ - static ClientNamespacedWriteModel updateMany( + static ClientNamespacedUpdateManyModel updateMany( final MongoNamespace namespace, final Bson filter, final Iterable updatePipeline, final ClientUpdateOptions options) { notNull("namespace", namespace); notNull("filter", filter); @@ -221,11 +223,11 @@ static ClientNamespacedWriteModel updateMany( * @param filter The filter. * @param replacement The replacement. * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. - * @return The requested {@link ClientReplaceOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedReplaceOneModel}. * @param The document type, for example {@link Document}. * @see Filters */ - static ClientNamespacedWriteModel replaceOne(final MongoNamespace namespace, final Bson filter, final TDocument replacement) { + static ClientNamespacedReplaceOneModel replaceOne(final MongoNamespace namespace, final Bson filter, final TDocument replacement) { notNull("namespace", namespace); notNull("filter", filter); notNull("replacement", replacement); @@ -240,11 +242,11 @@ static ClientNamespacedWriteModel replaceOne(final MongoNamespace na * @param replacement The replacement. * The keys of this document must not start with {@code $}, unless they express a {@linkplain com.mongodb.DBRef database reference}. * @param options The options. - * @return The requested {@link ClientReplaceOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedReplaceOneModel}. * @param The document type, for example {@link Document}. * @see Filters */ - static ClientNamespacedWriteModel replaceOne( + static ClientNamespacedReplaceOneModel replaceOne( final MongoNamespace namespace, final Bson filter, final TDocument replacement, final ClientReplaceOptions options) { notNull("namespace", namespace); notNull("filter", filter); @@ -260,10 +262,10 @@ static ClientNamespacedWriteModel replaceOne( * * @param namespace The namespace. * @param filter The filter. - * @return The requested {@link ClientDeleteOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedDeleteOneModel}. * @see Filters */ - static ClientNamespacedWriteModel deleteOne(final MongoNamespace namespace, final Bson filter) { + static ClientNamespacedDeleteOneModel deleteOne(final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteOneModel(filter, null)); @@ -275,10 +277,10 @@ static ClientNamespacedWriteModel deleteOne(final MongoNamespace namespace, fina * @param namespace The namespace. * @param filter The filter. * @param options The options. - * @return The requested {@link ClientDeleteOneModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedDeleteOneModel}. * @see Filters */ - static ClientNamespacedWriteModel deleteOne(final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { + static ClientNamespacedDeleteOneModel deleteOne(final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); @@ -292,10 +294,10 @@ static ClientNamespacedWriteModel deleteOne(final MongoNamespace namespace, fina * * @param namespace The namespace. * @param filter The filter. - * @return The requested {@link ClientDeleteManyModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedDeleteManyModel}. * @see Filters */ - static ClientNamespacedWriteModel deleteMany(final MongoNamespace namespace, final Bson filter) { + static ClientNamespacedDeleteManyModel deleteMany(final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteManyModel(filter, null)); @@ -307,10 +309,10 @@ static ClientNamespacedWriteModel deleteMany(final MongoNamespace namespace, fin * @param namespace The namespace. * @param filter The filter. * @param options The options. - * @return The requested {@link ClientDeleteManyModel} model with the {@code namespace}. + * @return The requested {@link ClientNamespacedDeleteManyModel}. * @see Filters */ - static ClientNamespacedWriteModel deleteMany(final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { + static ClientNamespacedDeleteManyModel deleteMany(final MongoNamespace namespace, final Bson filter, final ClientDeleteOptions options) { notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java index 1392b7ec0c7..447935290d4 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java @@ -22,7 +22,7 @@ import java.util.Optional; /** - * The result of a successful {@linkplain ClientWriteModel individual update or replace operation}. + * The result of a successful {@linkplain ClientNamespacedWriteModel individual update or replace operation}. * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. * * @since 5.3 diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientWriteModel.java similarity index 83% rename from driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientWriteModel.java index 53f5adbd223..56d431ec0e8 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientWriteModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ClientWriteModel.java @@ -13,15 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mongodb.client.model.bulk; - -import com.mongodb.annotations.Sealed; +package com.mongodb.internal.client.model.bulk; /** * An individual write operation to be executed as part of a client-level bulk write operation. - * - * @since 5.3 + *

      + * This class is not part of the public API and may be removed or changed at any time.

      */ -@Sealed public interface ClientWriteModel { } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java index 46fe39b489c..c02302ab5ea 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.client.model.bulk.ClientDeleteManyModel; import com.mongodb.client.model.bulk.ClientDeleteOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -23,7 +22,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientDeleteManyModel extends ConcreteClientDeleteOneModel implements ClientDeleteManyModel { +public final class ConcreteClientDeleteManyModel extends ConcreteClientDeleteOneModel implements ClientWriteModel { public ConcreteClientDeleteManyModel(final Bson filter, @Nullable final ClientDeleteOptions options) { super(filter, options); } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java index f002db8f044..09fc0d197c9 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.client.model.bulk.ClientDeleteOneModel; import com.mongodb.client.model.bulk.ClientDeleteOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -23,7 +22,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ConcreteClientDeleteOneModel implements ClientDeleteOneModel { +public class ConcreteClientDeleteOneModel implements ClientWriteModel { private final Bson filter; private final ConcreteClientDeleteOptions options; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java index cea73651c45..02315bd04c1 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java @@ -15,12 +15,10 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.client.model.bulk.ClientInsertOneModel; - /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientInsertOneModel implements ClientInsertOneModel { +public final class ConcreteClientInsertOneModel implements ClientWriteModel { private final Object document; public ConcreteClientInsertOneModel(final Object document) { diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java index 8027fb73bce..feb5ed0ce94 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java @@ -17,13 +17,23 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; -import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientNamespacedDeleteManyModel; +import com.mongodb.client.model.bulk.ClientNamespacedDeleteOneModel; +import com.mongodb.client.model.bulk.ClientNamespacedInsertOneModel; +import com.mongodb.client.model.bulk.ClientNamespacedReplaceOneModel; +import com.mongodb.client.model.bulk.ClientNamespacedUpdateManyModel; +import com.mongodb.client.model.bulk.ClientNamespacedUpdateOneModel; /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientNamespacedWriteModel implements ClientNamespacedWriteModel { +public final class ConcreteClientNamespacedWriteModel + implements ClientNamespacedInsertOneModel, + ClientNamespacedUpdateOneModel, + ClientNamespacedUpdateManyModel, + ClientNamespacedReplaceOneModel, + ClientNamespacedDeleteOneModel, + ClientNamespacedDeleteManyModel { private final MongoNamespace namespace; private final ClientWriteModel model; @@ -36,7 +46,7 @@ public MongoNamespace getNamespace() { return namespace; } - public ClientWriteModel getModel() { + public ClientWriteModel getModel() {// VAKOTODO non-public exposed? return model; } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java index 608e42ca705..f8242f16aa8 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.client.model.bulk.ClientReplaceOneModel; import com.mongodb.client.model.bulk.ClientReplaceOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -23,7 +22,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientReplaceOneModel implements ClientReplaceOneModel { +public final class ConcreteClientReplaceOneModel implements ClientWriteModel { private final Bson filter; private final Object replacement; private final ConcreteClientReplaceOptions options; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java index a6754342634..42465c12c1b 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java @@ -16,7 +16,6 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.assertions.Assertions; -import com.mongodb.client.model.bulk.ClientUpdateManyModel; import com.mongodb.client.model.bulk.ClientUpdateOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -24,7 +23,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientUpdateManyModel extends ConcreteClientUpdateOneModel implements ClientUpdateManyModel { +public final class ConcreteClientUpdateManyModel extends ConcreteClientUpdateOneModel implements ClientWriteModel { public ConcreteClientUpdateManyModel( final Bson filter, @Nullable diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java index e237fed6608..cf9327ef724 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.client.model.bulk.ClientUpdateOneModel; import com.mongodb.client.model.bulk.ClientUpdateOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -28,7 +27,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ConcreteClientUpdateOneModel implements ClientUpdateOneModel { +public class ConcreteClientUpdateOneModel implements ClientWriteModel { private final Bson filter; @Nullable private final Bson update; diff --git a/driver-sync/src/main/com/mongodb/client/MongoCluster.java b/driver-sync/src/main/com/mongodb/client/MongoCluster.java index 264ea22d4ac..f097f71288f 100644 --- a/driver-sync/src/main/com/mongodb/client/MongoCluster.java +++ b/driver-sync/src/main/com/mongodb/client/MongoCluster.java @@ -28,9 +28,9 @@ import com.mongodb.annotations.Immutable; import com.mongodb.annotations.Reason; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientDeleteManyModel; +import com.mongodb.client.model.bulk.ClientNamespacedDeleteManyModel; +import com.mongodb.client.model.bulk.ClientNamespacedUpdateManyModel; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; -import com.mongodb.client.model.bulk.ClientUpdateManyModel; import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.lang.Nullable; import org.bson.Document; @@ -370,7 +370,7 @@ public interface MongoCluster { * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: - * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + * {@link ClientNamespacedUpdateManyModel}, {@link ClientNamespacedDeleteManyModel} in a command render it non-retryable.

      *

      * This operation is not supported by MongoDB Atlas Serverless instances.

      * @@ -394,7 +394,7 @@ public interface MongoCluster { * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: - * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + * {@link ClientNamespacedUpdateManyModel}, {@link ClientNamespacedDeleteManyModel} in a command render it non-retryable.

      *

      * This operation is not supported by MongoDB Atlas Serverless instances.

      * @@ -423,7 +423,7 @@ ClientBulkWriteResult bulkWrite( * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: - * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + * {@link ClientNamespacedUpdateManyModel}, {@link ClientNamespacedDeleteManyModel} in a command render it non-retryable.

      *

      * This operation is not supported by MongoDB Atlas Serverless instances.

      * @@ -450,7 +450,7 @@ ClientBulkWriteResult bulkWrite( * Depending on the number of {@code models}, encoded size of {@code models}, and the size limits in effect, * executing this operation may require multiple {@code bulkWrite} commands. * The eligibility for retries is determined per each {@code bulkWrite} command: - * {@link ClientUpdateManyModel}, {@link ClientDeleteManyModel} in a command render it non-retryable.

      + * {@link ClientNamespacedUpdateManyModel}, {@link ClientNamespacedDeleteManyModel} in a command render it non-retryable.

      *

      * This operation is not supported by MongoDB Atlas Serverless instances.

      * From 310426ad87bc40af2fda958681ee3e51a86aa560 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 3 Sep 2024 13:29:40 -0600 Subject: [PATCH 41/59] Fixes after the merge JAVA-5528 --- .../operation/ClientBulkWriteOperation.java | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index a00524ebdcd..c223543b132 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -31,13 +31,8 @@ import com.mongodb.bulk.WriteConcernError; import com.mongodb.client.cursor.TimeoutMode; import com.mongodb.client.model.bulk.ClientBulkWriteOptions; -import com.mongodb.client.model.bulk.ClientDeleteManyModel; -import com.mongodb.client.model.bulk.ClientDeleteOneModel; -import com.mongodb.client.model.bulk.ClientInsertOneModel; -import com.mongodb.client.model.bulk.ClientReplaceOneModel; -import com.mongodb.client.model.bulk.ClientUpdateManyModel; -import com.mongodb.client.model.bulk.ClientUpdateOneModel; -import com.mongodb.client.model.bulk.ClientWriteModel; +import com.mongodb.client.model.bulk.ClientNamespacedReplaceOneModel; +import com.mongodb.client.model.bulk.ClientNamespacedUpdateOneModel; import com.mongodb.client.model.bulk.ClientNamespacedWriteModel; import com.mongodb.client.model.bulk.ClientBulkWriteResult; import com.mongodb.client.model.bulk.ClientDeleteResult; @@ -48,6 +43,7 @@ import com.mongodb.internal.async.function.RetryState; import com.mongodb.internal.binding.ConnectionSource; import com.mongodb.internal.binding.WriteBinding; +import com.mongodb.internal.client.model.bulk.ClientWriteModel; import com.mongodb.internal.client.model.bulk.ConcreteClientBulkWriteOptions; import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteManyModel; import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOneModel; @@ -347,7 +343,7 @@ public void encode(final BsonWriter writer, final String commandName, final Enco encodeUsingRegistry(writer, value); }); Function modelSupportsRetries = model -> - !(model instanceof ClientUpdateManyModel || model instanceof ClientDeleteManyModel); + !(model instanceof ConcreteClientUpdateManyModel || model instanceof ConcreteClientDeleteManyModel); assertFalse(unexecutedModels.isEmpty()); LinkedHashMap indexedNamespaces = new LinkedHashMap<>(); writer.writeStartArray("ops"); @@ -435,8 +431,8 @@ private static MongoWriteConcernException createWriteConcernException( private static final class FieldNameValidators { /** - * The server supports only the {@code update} individual write operation in the {@code ops} array field, - * while the driver supports {@link ClientUpdateOneModel}, {@link ClientUpdateOneModel}, {@link ClientReplaceOneModel}. + * The server supports only the {@code update} individual write operation in the {@code ops} array field, while the driver supports + * {@link ClientNamespacedUpdateOneModel}, {@link ClientNamespacedUpdateOneModel}, {@link ClientNamespacedReplaceOneModel}. * The difference between updating and replacing is only in the document specified via the {@code updateMods} field: *
        *
      • if the name of the first field starts with {@code '$'}, then the document is interpreted as specifying update operators;
      • @@ -481,7 +477,7 @@ public FieldNameValidator getValidatorForField(final String fieldName) { } private boolean currentIndividualOperationIsReplace() { - return getModelWithNamespace(models, currentIndividualOperationIndex).getModel() instanceof ClientReplaceOneModel; + return getModelWithNamespace(models, currentIndividualOperationIndex).getModel() instanceof ConcreteClientReplaceOneModel; } } @@ -686,11 +682,11 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final if (individualOperationResponse.getNumber("ok").intValue() == 1) { assertTrue(verboseResultsSetting); ClientWriteModel writeModel = getModelWithNamespace(models, writeModelIndexInBatch).getModel(); - if (writeModel instanceof ClientInsertOneModel) { + if (writeModel instanceof ConcreteClientInsertOneModel) { insertResults.put( writeModelIndexInBatch, new ConcreteClientInsertOneResult(insertModelDocumentIds.get(individualOperationIndexInBatch))); - } else if (writeModel instanceof ClientUpdateOneModel || writeModel instanceof ClientReplaceOneModel) { + } else if (writeModel instanceof ConcreteClientUpdateOneModel || writeModel instanceof ConcreteClientReplaceOneModel) { BsonDocument upsertedIdDocument = individualOperationResponse.getDocument("upserted", null); updateResults.put( writeModelIndexInBatch, @@ -698,7 +694,7 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final individualOperationResponse.getInt32("n").getValue(), individualOperationResponse.getInt32("nModified").getValue(), upsertedIdDocument == null ? null : upsertedIdDocument.get("_id"))); - } else if (writeModel instanceof ClientDeleteOneModel) { + } else if (writeModel instanceof ConcreteClientDeleteOneModel) { deleteResults.put( writeModelIndexInBatch, new ConcreteClientDeleteResult(individualOperationResponse.getInt32("n").getValue())); From 301a2ba0d40579a96087de2cfdff3e4028fe82cd Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 3 Sep 2024 13:42:10 -0600 Subject: [PATCH 42/59] Remove a garbage comment JAVA-5527 --- .../client/model/bulk/ConcreteClientNamespacedWriteModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java index feb5ed0ce94..fc29dd399fb 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java @@ -46,7 +46,7 @@ public MongoNamespace getNamespace() { return namespace; } - public ClientWriteModel getModel() {// VAKOTODO non-public exposed? + public ClientWriteModel getModel() { return model; } From 6f01e61b750dd1dadebe75d8f635cc52992bb7a6 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 9 Sep 2024 10:09:19 -0600 Subject: [PATCH 43/59] Replace `ConcreteClientNamespacedWriteModel` with multiple more specific concrete types JAVA-5527 --- .../bulk/ClientNamespacedWriteModel.java | 37 +++++++++++-------- ...> AbstractClientNamespacedWriteModel.java} | 25 +++---------- ...ncreteClientNamespacedDeleteManyModel.java | 28 ++++++++++++++ ...oncreteClientNamespacedDeleteOneModel.java | 28 ++++++++++++++ ...oncreteClientNamespacedInsertOneModel.java | 28 ++++++++++++++ ...ncreteClientNamespacedReplaceOneModel.java | 28 ++++++++++++++ ...ncreteClientNamespacedUpdateManyModel.java | 28 ++++++++++++++ ...oncreteClientNamespacedUpdateOneModel.java | 28 ++++++++++++++ 8 files changed, 194 insertions(+), 36 deletions(-) rename driver-core/src/main/com/mongodb/internal/client/model/bulk/{ConcreteClientNamespacedWriteModel.java => AbstractClientNamespacedWriteModel.java} (50%) create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteManyModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteOneModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedInsertOneModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedReplaceOneModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateManyModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateOneModel.java diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java index 388113530c7..448be5b06a3 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java @@ -24,7 +24,12 @@ import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteManyModel; import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientInsertOneModel; -import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedWriteModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedDeleteManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedDeleteOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedInsertOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedReplaceOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedUpdateManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedUpdateOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; @@ -53,7 +58,7 @@ public interface ClientNamespacedWriteModel { static ClientNamespacedInsertOneModel insertOne(final MongoNamespace namespace, final TDocument document) { notNull("namespace", namespace); notNull("document", document); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientInsertOneModel(document)); + return new ConcreteClientNamespacedInsertOneModel(namespace, new ConcreteClientInsertOneModel(document)); } /** @@ -72,7 +77,7 @@ static ClientNamespacedUpdateOneModel updateOne(final MongoNamespace namespace, notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, update, null, null)); + return new ConcreteClientNamespacedUpdateOneModel(namespace, new ConcreteClientUpdateOneModel(filter, update, null, null)); } /** @@ -92,7 +97,7 @@ static ClientNamespacedUpdateOneModel updateOne( notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, update, null, options)); + return new ConcreteClientNamespacedUpdateOneModel(namespace, new ConcreteClientUpdateOneModel(filter, update, null, options)); } /** @@ -112,7 +117,7 @@ static ClientNamespacedUpdateOneModel updateOne( notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, null, updatePipeline, null)); + return new ConcreteClientNamespacedUpdateOneModel(namespace, new ConcreteClientUpdateOneModel(filter, null, updatePipeline, null)); } /** @@ -132,7 +137,7 @@ static ClientNamespacedUpdateOneModel updateOne( notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateOneModel(filter, null, updatePipeline, options)); + return new ConcreteClientNamespacedUpdateOneModel(namespace, new ConcreteClientUpdateOneModel(filter, null, updatePipeline, options)); } /** @@ -151,7 +156,7 @@ static ClientNamespacedUpdateManyModel updateMany(final MongoNamespace namespace notNull("namespace", namespace); notNull("filter", filter); notNull("update", update); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, update, null, null)); + return new ConcreteClientNamespacedUpdateManyModel(namespace, new ConcreteClientUpdateManyModel(filter, update, null, null)); } /** @@ -171,7 +176,7 @@ static ClientNamespacedUpdateManyModel updateMany( notNull("filter", filter); notNull("update", update); notNull("options", options); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, update, null, options)); + return new ConcreteClientNamespacedUpdateManyModel(namespace, new ConcreteClientUpdateManyModel(filter, update, null, options)); } /** @@ -191,7 +196,7 @@ static ClientNamespacedUpdateManyModel updateMany( notNull("namespace", namespace); notNull("filter", filter); notNull("updatePipeline", updatePipeline); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, null, updatePipeline, null)); + return new ConcreteClientNamespacedUpdateManyModel(namespace, new ConcreteClientUpdateManyModel(filter, null, updatePipeline, null)); } /** @@ -211,7 +216,7 @@ static ClientNamespacedUpdateManyModel updateMany( notNull("filter", filter); notNull("updatePipeline", updatePipeline); notNull("options", options); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientUpdateManyModel(filter, null, updatePipeline, options)); + return new ConcreteClientNamespacedUpdateManyModel(namespace, new ConcreteClientUpdateManyModel(filter, null, updatePipeline, options)); } /** @@ -231,7 +236,7 @@ static ClientNamespacedReplaceOneModel replaceOne(final MongoNamespa notNull("namespace", namespace); notNull("filter", filter); notNull("replacement", replacement); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientReplaceOneModel(filter, replacement, null)); + return new ConcreteClientNamespacedReplaceOneModel(namespace, new ConcreteClientReplaceOneModel(filter, replacement, null)); } /** @@ -252,7 +257,7 @@ static ClientNamespacedReplaceOneModel replaceOne( notNull("filter", filter); notNull("replacement", replacement); notNull("options", options); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientReplaceOneModel(filter, replacement, options)); + return new ConcreteClientNamespacedReplaceOneModel(namespace, new ConcreteClientReplaceOneModel(filter, replacement, options)); } /** @@ -268,7 +273,7 @@ static ClientNamespacedReplaceOneModel replaceOne( static ClientNamespacedDeleteOneModel deleteOne(final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteOneModel(filter, null)); + return new ConcreteClientNamespacedDeleteOneModel(namespace, new ConcreteClientDeleteOneModel(filter, null)); } /** @@ -284,7 +289,7 @@ static ClientNamespacedDeleteOneModel deleteOne(final MongoNamespace namespace, notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteOneModel(filter, options)); + return new ConcreteClientNamespacedDeleteOneModel(namespace, new ConcreteClientDeleteOneModel(filter, options)); } /** @@ -300,7 +305,7 @@ static ClientNamespacedDeleteOneModel deleteOne(final MongoNamespace namespace, static ClientNamespacedDeleteManyModel deleteMany(final MongoNamespace namespace, final Bson filter) { notNull("namespace", namespace); notNull("filter", filter); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteManyModel(filter, null)); + return new ConcreteClientNamespacedDeleteManyModel(namespace, new ConcreteClientDeleteManyModel(filter, null)); } /** @@ -316,6 +321,6 @@ static ClientNamespacedDeleteManyModel deleteMany(final MongoNamespace namespace notNull("namespace", namespace); notNull("filter", filter); notNull("options", options); - return new ConcreteClientNamespacedWriteModel(namespace, new ConcreteClientDeleteManyModel(filter, options)); + return new ConcreteClientNamespacedDeleteManyModel(namespace, new ConcreteClientDeleteManyModel(filter, options)); } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientNamespacedWriteModel.java similarity index 50% rename from driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java rename to driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientNamespacedWriteModel.java index fc29dd399fb..fe004d42b47 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedWriteModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientNamespacedWriteModel.java @@ -17,41 +17,26 @@ package com.mongodb.internal.client.model.bulk; import com.mongodb.MongoNamespace; -import com.mongodb.client.model.bulk.ClientNamespacedDeleteManyModel; -import com.mongodb.client.model.bulk.ClientNamespacedDeleteOneModel; -import com.mongodb.client.model.bulk.ClientNamespacedInsertOneModel; -import com.mongodb.client.model.bulk.ClientNamespacedReplaceOneModel; -import com.mongodb.client.model.bulk.ClientNamespacedUpdateManyModel; -import com.mongodb.client.model.bulk.ClientNamespacedUpdateOneModel; -/** - * This class is not part of the public API and may be removed or changed at any time. - */ -public final class ConcreteClientNamespacedWriteModel - implements ClientNamespacedInsertOneModel, - ClientNamespacedUpdateOneModel, - ClientNamespacedUpdateManyModel, - ClientNamespacedReplaceOneModel, - ClientNamespacedDeleteOneModel, - ClientNamespacedDeleteManyModel { +abstract class AbstractClientNamespacedWriteModel { private final MongoNamespace namespace; private final ClientWriteModel model; - public ConcreteClientNamespacedWriteModel(final MongoNamespace namespace, final ClientWriteModel model) { + AbstractClientNamespacedWriteModel(final MongoNamespace namespace, final ClientWriteModel model) { this.namespace = namespace; this.model = model; } - public MongoNamespace getNamespace() { + public final MongoNamespace getNamespace() { return namespace; } - public ClientWriteModel getModel() { + public final ClientWriteModel getModel() { return model; } @Override - public String toString() { + public final String toString() { return "ClientNamespacedWriteModel{" + "namespace=" + namespace + ", model=" + model diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteManyModel.java new file mode 100644 index 00000000000..4deb566cff1 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteManyModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedDeleteManyModel; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientNamespacedDeleteManyModel extends AbstractClientNamespacedWriteModel implements ClientNamespacedDeleteManyModel { + public ConcreteClientNamespacedDeleteManyModel(final MongoNamespace namespace, final ClientWriteModel model) { + super(namespace, model); + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteOneModel.java new file mode 100644 index 00000000000..db8a7ad9fde --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedDeleteOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedDeleteOneModel; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientNamespacedDeleteOneModel extends AbstractClientNamespacedWriteModel implements ClientNamespacedDeleteOneModel { + public ConcreteClientNamespacedDeleteOneModel(final MongoNamespace namespace, final ClientWriteModel model) { + super(namespace, model); + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedInsertOneModel.java new file mode 100644 index 00000000000..e80861b947e --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedInsertOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedInsertOneModel; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientNamespacedInsertOneModel extends AbstractClientNamespacedWriteModel implements ClientNamespacedInsertOneModel { + public ConcreteClientNamespacedInsertOneModel(final MongoNamespace namespace, final ClientWriteModel model) { + super(namespace, model); + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedReplaceOneModel.java new file mode 100644 index 00000000000..96ea786169e --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedReplaceOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedReplaceOneModel; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientNamespacedReplaceOneModel extends AbstractClientNamespacedWriteModel implements ClientNamespacedReplaceOneModel { + public ConcreteClientNamespacedReplaceOneModel(final MongoNamespace namespace, final ClientWriteModel model) { + super(namespace, model); + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateManyModel.java new file mode 100644 index 00000000000..28f281287e0 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateManyModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedUpdateManyModel; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientNamespacedUpdateManyModel extends AbstractClientNamespacedWriteModel implements ClientNamespacedUpdateManyModel { + public ConcreteClientNamespacedUpdateManyModel(final MongoNamespace namespace, final ClientWriteModel model) { + super(namespace, model); + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateOneModel.java new file mode 100644 index 00000000000..ad3aa0853ab --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientNamespacedUpdateOneModel.java @@ -0,0 +1,28 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.MongoNamespace; +import com.mongodb.client.model.bulk.ClientNamespacedUpdateOneModel; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public final class ConcreteClientNamespacedUpdateOneModel extends AbstractClientNamespacedWriteModel implements ClientNamespacedUpdateOneModel { + public ConcreteClientNamespacedUpdateOneModel(final MongoNamespace namespace, final ClientWriteModel model) { + super(namespace, model); + } +} From c3224e912b0777a63945d3b718e06fa679afbcf4 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 9 Sep 2024 10:12:42 -0600 Subject: [PATCH 44/59] Rearrange `ClientWriteModel` inheritance: "one" should extend "many", not vice versa JAVA-5527 --- .../bulk/ConcreteClientDeleteManyModel.java | 20 +++++++-- .../bulk/ConcreteClientDeleteOneModel.java | 20 ++------- .../bulk/ConcreteClientUpdateManyModel.java | 45 +++++++++++++++---- .../bulk/ConcreteClientUpdateOneModel.java | 45 ++++--------------- 4 files changed, 65 insertions(+), 65 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java index c02302ab5ea..640fab22d71 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java @@ -22,16 +22,28 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientDeleteManyModel extends ConcreteClientDeleteOneModel implements ClientWriteModel { +public class ConcreteClientDeleteManyModel implements ClientWriteModel { + private final Bson filter; + private final ConcreteClientDeleteOptions options; + public ConcreteClientDeleteManyModel(final Bson filter, @Nullable final ClientDeleteOptions options) { - super(filter, options); + this.filter = filter; + this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; + } + + public Bson getFilter() { + return filter; + } + + public ConcreteClientDeleteOptions getOptions() { + return options; } @Override public String toString() { return "ClientDeleteManyModel{" - + ", filter=" + getFilter() - + ", options=" + getOptions() + + ", filter=" + filter + + ", options=" + options + '}'; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java index 09fc0d197c9..e5db8af9711 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java @@ -22,28 +22,16 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ConcreteClientDeleteOneModel implements ClientWriteModel { - private final Bson filter; - private final ConcreteClientDeleteOptions options; - +public final class ConcreteClientDeleteOneModel extends ConcreteClientDeleteManyModel { public ConcreteClientDeleteOneModel(final Bson filter, @Nullable final ClientDeleteOptions options) { - this.filter = filter; - this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; - } - - public Bson getFilter() { - return filter; - } - - public ConcreteClientDeleteOptions getOptions() { - return options; + super(filter, options); } @Override public String toString() { return "ClientDeleteOneModel{" - + ", filter=" + filter - + ", options=" + options + + ", filter=" + getFilter() + + ", options=" + getOptions() + '}'; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java index 42465c12c1b..c01b3999caf 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java @@ -15,15 +15,26 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.assertions.Assertions; import com.mongodb.client.model.bulk.ClientUpdateOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; +import java.util.Optional; + +import static com.mongodb.assertions.Assertions.assertTrue; +import static java.util.Optional.ofNullable; + /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientUpdateManyModel extends ConcreteClientUpdateOneModel implements ClientWriteModel { +public class ConcreteClientUpdateManyModel implements ClientWriteModel { + private final Bson filter; + @Nullable + private final Bson update; + @Nullable + private final Iterable updatePipeline; + private final ConcreteClientUpdateOptions options; + public ConcreteClientUpdateManyModel( final Bson filter, @Nullable @@ -31,17 +42,35 @@ public ConcreteClientUpdateManyModel( @Nullable final Iterable updatePipeline, @Nullable final ClientUpdateOptions options) { - super(filter, update, updatePipeline, options); + this.filter = filter; + assertTrue(update == null ^ updatePipeline == null); + this.update = update; + this.updatePipeline = updatePipeline; + this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; + } + + public Bson getFilter() { + return filter; + } + + public Optional getUpdate() { + return ofNullable(update); + } + + public Optional> getUpdatePipeline() { + return ofNullable(updatePipeline); + } + + public ConcreteClientUpdateOptions getOptions() { + return options; } @Override public String toString() { return "ClientUpdateManyModel{" - + ", filter=" + getFilter() - + ", update=" + getUpdate().map(Object::toString) - .orElse(getUpdatePipeline().map(Object::toString) - .orElseThrow(Assertions::fail)) - + ", options=" + getOptions() + + ", filter=" + filter + + ", update=" + (update != null ? update : updatePipeline) + + ", options=" + options + '}'; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java index cf9327ef724..865a778ab9f 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java @@ -15,26 +15,15 @@ */ package com.mongodb.internal.client.model.bulk; +import com.mongodb.assertions.Assertions; import com.mongodb.client.model.bulk.ClientUpdateOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; -import java.util.Optional; - -import static com.mongodb.assertions.Assertions.assertTrue; -import static java.util.Optional.ofNullable; - /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ConcreteClientUpdateOneModel implements ClientWriteModel { - private final Bson filter; - @Nullable - private final Bson update; - @Nullable - private final Iterable updatePipeline; - private final ConcreteClientUpdateOptions options; - +public final class ConcreteClientUpdateOneModel extends ConcreteClientUpdateManyModel { public ConcreteClientUpdateOneModel( final Bson filter, @Nullable @@ -42,35 +31,17 @@ public ConcreteClientUpdateOneModel( @Nullable final Iterable updatePipeline, @Nullable final ClientUpdateOptions options) { - this.filter = filter; - assertTrue(update == null ^ updatePipeline == null); - this.update = update; - this.updatePipeline = updatePipeline; - this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; - } - - public Bson getFilter() { - return filter; - } - - public Optional getUpdate() { - return ofNullable(update); - } - - public Optional> getUpdatePipeline() { - return ofNullable(updatePipeline); - } - - public ConcreteClientUpdateOptions getOptions() { - return options; + super(filter, update, updatePipeline, options); } @Override public String toString() { return "ClientUpdateOneModel{" - + ", filter=" + filter - + ", update=" + (update != null ? update : updatePipeline) - + ", options=" + options + + ", filter=" + getFilter() + + ", update=" + getUpdate().map(Object::toString) + .orElse(getUpdatePipeline().map(Object::toString) + .orElseThrow(Assertions::fail)) + + ", options=" + getOptions() + '}'; } } From c05739054c8a1aa758fff1fc73cce2eaaa477b87 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 9 Sep 2024 10:19:44 -0600 Subject: [PATCH 45/59] Make internal `AbstractClientNamespacedWriteModel` public JAVA-5527 --- .../model/bulk/AbstractClientNamespacedWriteModel.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientNamespacedWriteModel.java index fe004d42b47..25daa0bea15 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientNamespacedWriteModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientNamespacedWriteModel.java @@ -18,7 +18,10 @@ import com.mongodb.MongoNamespace; -abstract class AbstractClientNamespacedWriteModel { +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public abstract class AbstractClientNamespacedWriteModel { private final MongoNamespace namespace; private final ClientWriteModel model; From dbb6ec855a46fbd70e3e0e6d86d6be8ce49392ab Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 9 Sep 2024 11:11:59 -0600 Subject: [PATCH 46/59] Rearrange `ClientWriteModel` inheritance: neither "one" nor "many" should extend each other Such extending turned out to be confusing JAVA-5527 --- .../model/bulk/AbstractClientDeleteModel.java | 51 +++++++++++++ .../model/bulk/AbstractClientUpdateModel.java | 75 +++++++++++++++++++ ...nowledgedVerboseClientBulkWriteResult.java | 2 +- .../bulk/ConcreteClientDeleteManyModel.java | 23 +----- .../bulk/ConcreteClientDeleteOneModel.java | 9 +-- .../bulk/ConcreteClientInsertOneModel.java | 2 +- .../bulk/ConcreteClientReplaceOneModel.java | 2 +- .../bulk/ConcreteClientUpdateManyModel.java | 44 +---------- .../bulk/ConcreteClientUpdateOneModel.java | 13 +--- 9 files changed, 143 insertions(+), 78 deletions(-) create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java create mode 100644 driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java new file mode 100644 index 00000000000..b2026d460d6 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java @@ -0,0 +1,51 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.client.model.bulk.ClientDeleteOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +abstract class AbstractClientDeleteModel implements ClientWriteModel { + private final Bson filter; + private final ConcreteClientDeleteOptions options; + + AbstractClientDeleteModel(final Bson filter, @Nullable final ClientDeleteOptions options) { + this.filter = filter; + this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; + } + + public final Bson getFilter() { + return filter; + } + + public final ConcreteClientDeleteOptions getOptions() { + return options; + } + + abstract String getToStringDescription(); + + @Override + public final String toString() { + return getToStringDescription() + + "{filter=" + filter + + ", options=" + options + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java new file mode 100644 index 00000000000..7d8b4072de2 --- /dev/null +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java @@ -0,0 +1,75 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mongodb.internal.client.model.bulk; + +import com.mongodb.client.model.bulk.ClientUpdateOptions; +import com.mongodb.lang.Nullable; +import org.bson.conversions.Bson; + +import java.util.Optional; + +import static com.mongodb.assertions.Assertions.assertTrue; +import static java.util.Optional.ofNullable; + +abstract class AbstractClientUpdateModel { + private final Bson filter; + @Nullable + private final Bson update; + @Nullable + private final Iterable updatePipeline; + private final ConcreteClientUpdateOptions options; + + AbstractClientUpdateModel( + final Bson filter, + @Nullable + final Bson update, + @Nullable + final Iterable updatePipeline, + @Nullable final ClientUpdateOptions options) { + this.filter = filter; + assertTrue(update == null ^ updatePipeline == null); + this.update = update; + this.updatePipeline = updatePipeline; + this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; + } + + public final Bson getFilter() { + return filter; + } + + public final Optional getUpdate() { + return ofNullable(update); + } + + public final Optional> getUpdatePipeline() { + return ofNullable(updatePipeline); + } + + public final ConcreteClientUpdateOptions getOptions() { + return options; + } + + abstract String getToStringDescription(); + + @Override + public final String toString() { + return getToStringDescription() + + "{filter=" + filter + + ", update=" + (update != null ? update : updatePipeline) + + ", options=" + options + + '}'; + } +} diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java index 79e13b6478c..a5c83b5825a 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -160,7 +160,7 @@ public int hashCode() { @Override public String toString() { return "AcknowledgedVerboseClientBulkWriteResult.Verbose{" - + ", insertResults=" + insertResults + + "insertResults=" + insertResults + ", updateResults=" + updateResults + ", deleteResults=" + deleteResults + '}'; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java index 640fab22d71..7603c5a7df0 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteManyModel.java @@ -22,28 +22,13 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ConcreteClientDeleteManyModel implements ClientWriteModel { - private final Bson filter; - private final ConcreteClientDeleteOptions options; - +public final class ConcreteClientDeleteManyModel extends AbstractClientDeleteModel implements ClientWriteModel { public ConcreteClientDeleteManyModel(final Bson filter, @Nullable final ClientDeleteOptions options) { - this.filter = filter; - this.options = options == null ? ConcreteClientDeleteOptions.MUTABLE_EMPTY : (ConcreteClientDeleteOptions) options; - } - - public Bson getFilter() { - return filter; - } - - public ConcreteClientDeleteOptions getOptions() { - return options; + super(filter, options); } @Override - public String toString() { - return "ClientDeleteManyModel{" - + ", filter=" + filter - + ", options=" + options - + '}'; + String getToStringDescription() { + return "ClientDeleteManyModel"; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java index e5db8af9711..708f0d3e2ff 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientDeleteOneModel.java @@ -22,16 +22,13 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientDeleteOneModel extends ConcreteClientDeleteManyModel { +public final class ConcreteClientDeleteOneModel extends AbstractClientDeleteModel implements ClientWriteModel { public ConcreteClientDeleteOneModel(final Bson filter, @Nullable final ClientDeleteOptions options) { super(filter, options); } @Override - public String toString() { - return "ClientDeleteOneModel{" - + ", filter=" + getFilter() - + ", options=" + getOptions() - + '}'; + String getToStringDescription() { + return "ClientDeleteOneModel"; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java index 02315bd04c1..660944fc202 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientInsertOneModel.java @@ -32,7 +32,7 @@ public Object getDocument() { @Override public String toString() { return "ClientInsertOneModel{" - + ", document=" + document + + "document=" + document + '}'; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java index f8242f16aa8..3bdf08d424a 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientReplaceOneModel.java @@ -48,7 +48,7 @@ public ConcreteClientReplaceOptions getOptions() { @Override public String toString() { return "ClientReplaceOneModel{" - + ", filter=" + filter + + "filter=" + filter + ", replacement=" + replacement + ", options=" + options + '}'; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java index c01b3999caf..a7a0b1ac900 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateManyModel.java @@ -19,22 +19,10 @@ import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; -import java.util.Optional; - -import static com.mongodb.assertions.Assertions.assertTrue; -import static java.util.Optional.ofNullable; - /** * This class is not part of the public API and may be removed or changed at any time. */ -public class ConcreteClientUpdateManyModel implements ClientWriteModel { - private final Bson filter; - @Nullable - private final Bson update; - @Nullable - private final Iterable updatePipeline; - private final ConcreteClientUpdateOptions options; - +public final class ConcreteClientUpdateManyModel extends AbstractClientUpdateModel implements ClientWriteModel { public ConcreteClientUpdateManyModel( final Bson filter, @Nullable @@ -42,35 +30,11 @@ public ConcreteClientUpdateManyModel( @Nullable final Iterable updatePipeline, @Nullable final ClientUpdateOptions options) { - this.filter = filter; - assertTrue(update == null ^ updatePipeline == null); - this.update = update; - this.updatePipeline = updatePipeline; - this.options = options == null ? ConcreteClientUpdateOptions.MUTABLE_EMPTY : (ConcreteClientUpdateOptions) options; - } - - public Bson getFilter() { - return filter; - } - - public Optional getUpdate() { - return ofNullable(update); - } - - public Optional> getUpdatePipeline() { - return ofNullable(updatePipeline); - } - - public ConcreteClientUpdateOptions getOptions() { - return options; + super(filter, update, updatePipeline, options); } @Override - public String toString() { - return "ClientUpdateManyModel{" - + ", filter=" + filter - + ", update=" + (update != null ? update : updatePipeline) - + ", options=" + options - + '}'; + String getToStringDescription() { + return "ClientUpdateManyModel"; } } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java index 865a778ab9f..aa922a803c6 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/ConcreteClientUpdateOneModel.java @@ -15,7 +15,6 @@ */ package com.mongodb.internal.client.model.bulk; -import com.mongodb.assertions.Assertions; import com.mongodb.client.model.bulk.ClientUpdateOptions; import com.mongodb.lang.Nullable; import org.bson.conversions.Bson; @@ -23,7 +22,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -public final class ConcreteClientUpdateOneModel extends ConcreteClientUpdateManyModel { +public final class ConcreteClientUpdateOneModel extends AbstractClientUpdateModel implements ClientWriteModel { public ConcreteClientUpdateOneModel( final Bson filter, @Nullable @@ -35,13 +34,7 @@ public ConcreteClientUpdateOneModel( } @Override - public String toString() { - return "ClientUpdateOneModel{" - + ", filter=" + getFilter() - + ", update=" + getUpdate().map(Object::toString) - .orElse(getUpdatePipeline().map(Object::toString) - .orElseThrow(Assertions::fail)) - + ", options=" + getOptions() - + '}'; + String getToStringDescription() { + return "ClientUpdateOneModel"; } } From 8bd7a6af0260e6c70beca8a733ef60ef2cba2609 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 9 Sep 2024 11:44:37 -0600 Subject: [PATCH 47/59] Fixes after the merge JAVA-5528 --- .../model/bulk/AbstractClientDeleteModel.java | 2 +- .../model/bulk/AbstractClientUpdateModel.java | 5 +- .../operation/ClientBulkWriteOperation.java | 59 ++++++++++--------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java index b2026d460d6..3d3829661cf 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java @@ -22,7 +22,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -abstract class AbstractClientDeleteModel implements ClientWriteModel { +public abstract class AbstractClientDeleteModel implements ClientWriteModel { private final Bson filter; private final ConcreteClientDeleteOptions options; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java index 7d8b4072de2..2c8cadf3d88 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java @@ -24,7 +24,10 @@ import static com.mongodb.assertions.Assertions.assertTrue; import static java.util.Optional.ofNullable; -abstract class AbstractClientUpdateModel { +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public abstract class AbstractClientUpdateModel { private final Bson filter; @Nullable private final Bson update; diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index c223543b132..adf623ae491 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -43,18 +43,26 @@ import com.mongodb.internal.async.function.RetryState; import com.mongodb.internal.binding.ConnectionSource; import com.mongodb.internal.binding.WriteBinding; +import com.mongodb.internal.client.model.bulk.AbstractClientDeleteModel; +import com.mongodb.internal.client.model.bulk.AbstractClientNamespacedWriteModel; +import com.mongodb.internal.client.model.bulk.AbstractClientUpdateModel; import com.mongodb.internal.client.model.bulk.ClientWriteModel; import com.mongodb.internal.client.model.bulk.ConcreteClientBulkWriteOptions; import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteManyModel; import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteOptions; import com.mongodb.internal.client.model.bulk.ConcreteClientInsertOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedDeleteManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedDeleteOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedInsertOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedReplaceOneModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedUpdateManyModel; +import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedUpdateOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientReplaceOptions; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateManyModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOneModel; import com.mongodb.internal.client.model.bulk.ConcreteClientUpdateOptions; -import com.mongodb.internal.client.model.bulk.ConcreteClientNamespacedWriteModel; import com.mongodb.internal.client.model.bulk.AcknowledgedSummaryClientBulkWriteResult; import com.mongodb.internal.client.model.bulk.AcknowledgedVerboseClientBulkWriteResult; import com.mongodb.internal.client.model.bulk.ConcreteClientDeleteResult; @@ -349,7 +357,7 @@ public void encode(final BsonWriter writer, final String commandName, final Enco writer.writeStartArray("ops"); boolean commandIsRetryable = effectiveRetryWrites; for (int modelIndexInBatch = 0; modelIndexInBatch < unexecutedModels.size(); modelIndexInBatch++) { - ConcreteClientNamespacedWriteModel modelWithNamespace = getModelWithNamespace(unexecutedModels, modelIndexInBatch); + AbstractClientNamespacedWriteModel modelWithNamespace = getNamespacedModel(unexecutedModels, modelIndexInBatch); ClientWriteModel model = modelWithNamespace.getModel(); if (commandIsRetryable && !modelSupportsRetries.apply(model)) { commandIsRetryable = false; @@ -396,9 +404,9 @@ private void encodeUsingRegistry(final BsonWriter writer, final T value, fin collationEncoder.encode(writer, value, encoderContext); } - private static ConcreteClientNamespacedWriteModel getModelWithNamespace( + private static AbstractClientNamespacedWriteModel getNamespacedModel( final List models, final int index) { - return (ConcreteClientNamespacedWriteModel) models.get(index); + return (AbstractClientNamespacedWriteModel) models.get(index); } public static final class Exceptions { @@ -477,7 +485,7 @@ public FieldNameValidator getValidatorForField(final String fieldName) { } private boolean currentIndividualOperationIsReplace() { - return getModelWithNamespace(models, currentIndividualOperationIndex).getModel() instanceof ConcreteClientReplaceOneModel; + return getNamespacedModel(models, currentIndividualOperationIndex) instanceof ConcreteClientNamespacedReplaceOneModel; } } @@ -681,12 +689,14 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final int writeModelIndexInBatch = batchStartModelIndex + individualOperationIndexInBatch; if (individualOperationResponse.getNumber("ok").intValue() == 1) { assertTrue(verboseResultsSetting); - ClientWriteModel writeModel = getModelWithNamespace(models, writeModelIndexInBatch).getModel(); - if (writeModel instanceof ConcreteClientInsertOneModel) { + AbstractClientNamespacedWriteModel writeModel = getNamespacedModel(models, writeModelIndexInBatch); + if (writeModel instanceof ConcreteClientNamespacedInsertOneModel) { insertResults.put( writeModelIndexInBatch, new ConcreteClientInsertOneResult(insertModelDocumentIds.get(individualOperationIndexInBatch))); - } else if (writeModel instanceof ConcreteClientUpdateOneModel || writeModel instanceof ConcreteClientReplaceOneModel) { + } else if (writeModel instanceof ConcreteClientNamespacedUpdateOneModel + || writeModel instanceof ConcreteClientNamespacedUpdateManyModel + || writeModel instanceof ConcreteClientNamespacedReplaceOneModel) { BsonDocument upsertedIdDocument = individualOperationResponse.getDocument("upserted", null); updateResults.put( writeModelIndexInBatch, @@ -694,7 +704,8 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final individualOperationResponse.getInt32("n").getValue(), individualOperationResponse.getInt32("nModified").getValue(), upsertedIdDocument == null ? null : upsertedIdDocument.get("_id"))); - } else if (writeModel instanceof ConcreteClientDeleteOneModel) { + } else if (writeModel instanceof ConcreteClientNamespacedDeleteOneModel + || writeModel instanceof ConcreteClientNamespacedDeleteManyModel) { deleteResults.put( writeModelIndexInBatch, new ConcreteClientDeleteResult(individualOperationResponse.getInt32("n").getValue())); @@ -905,21 +916,25 @@ void encodeWriteModel( if (model instanceof ConcreteClientInsertOneModel) { writer.writeInt32("insert", namespaceIndexInBatch); encodeWriteModelInternals(writer, (ConcreteClientInsertOneModel) model, modelIndexInBatch); - } else if (model instanceof ConcreteClientUpdateManyModel) { - writer.writeInt32("update", namespaceIndexInBatch); - encodeWriteModelInternals(writer, (ConcreteClientUpdateManyModel) model); } else if (model instanceof ConcreteClientUpdateOneModel) { writer.writeInt32("update", namespaceIndexInBatch); + writer.writeBoolean("multi", false); encodeWriteModelInternals(writer, (ConcreteClientUpdateOneModel) model); + } else if (model instanceof ConcreteClientUpdateManyModel) { + writer.writeInt32("update", namespaceIndexInBatch); + writer.writeBoolean("multi", true); + encodeWriteModelInternals(writer, (ConcreteClientUpdateManyModel) model); } else if (model instanceof ConcreteClientReplaceOneModel) { writer.writeInt32("update", namespaceIndexInBatch); encodeWriteModelInternals(writer, (ConcreteClientReplaceOneModel) model); - } else if (model instanceof ConcreteClientDeleteManyModel) { - writer.writeInt32("delete", namespaceIndexInBatch); - encodeWriteModelInternals(writer, (ConcreteClientDeleteManyModel) model); } else if (model instanceof ConcreteClientDeleteOneModel) { writer.writeInt32("delete", namespaceIndexInBatch); + writer.writeBoolean("multi", false); encodeWriteModelInternals(writer, (ConcreteClientDeleteOneModel) model); + } else if (model instanceof ConcreteClientDeleteManyModel) { + writer.writeInt32("delete", namespaceIndexInBatch); + writer.writeBoolean("multi", true); + encodeWriteModelInternals(writer, (ConcreteClientDeleteManyModel) model); } else { throw fail(model.getClass().toString()); } @@ -942,12 +957,7 @@ private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteCl }); } - private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientUpdateManyModel model) { - encodeWriteModelInternals(writer, (ConcreteClientUpdateOneModel) model); - } - - private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientUpdateOneModel model) { - writer.writeBoolean("multi", model instanceof ConcreteClientUpdateManyModel); + private void encodeWriteModelInternals(final BsonWriter writer, final AbstractClientUpdateModel model) { writer.writeName("filter"); encodeUsingRegistry(writer, model.getFilter()); model.getUpdate().ifPresent(value -> { @@ -996,12 +1006,7 @@ private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteCl options.isUpsert().ifPresent(value -> writer.writeBoolean("upsert", value)); } - private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientDeleteManyModel model) { - encodeWriteModelInternals(writer, (ConcreteClientDeleteOneModel) model); - } - - private void encodeWriteModelInternals(final BsonWriter writer, final ConcreteClientDeleteOneModel model) { - writer.writeBoolean("multi", model instanceof ConcreteClientDeleteManyModel); + private void encodeWriteModelInternals(final BsonWriter writer, final AbstractClientDeleteModel model) { writer.writeName("filter"); encodeUsingRegistry(writer, model.getFilter()); ConcreteClientDeleteOptions options = model.getOptions(); From f781bca56b62e956a021e4280fcc022eb2d3a01a Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 9 Sep 2024 11:46:09 -0600 Subject: [PATCH 48/59] Make internal `AbstractClientUpdateModel`, `AbstractClientDeleteModel` public JAVA-5527 --- .../client/model/bulk/AbstractClientDeleteModel.java | 2 +- .../client/model/bulk/AbstractClientUpdateModel.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java index b2026d460d6..3d3829661cf 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientDeleteModel.java @@ -22,7 +22,7 @@ /** * This class is not part of the public API and may be removed or changed at any time. */ -abstract class AbstractClientDeleteModel implements ClientWriteModel { +public abstract class AbstractClientDeleteModel implements ClientWriteModel { private final Bson filter; private final ConcreteClientDeleteOptions options; diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java index 7d8b4072de2..2c8cadf3d88 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AbstractClientUpdateModel.java @@ -24,7 +24,10 @@ import static com.mongodb.assertions.Assertions.assertTrue; import static java.util.Optional.ofNullable; -abstract class AbstractClientUpdateModel { +/** + * This class is not part of the public API and may be removed or changed at any time. + */ +public abstract class AbstractClientUpdateModel { private final Bson filter; @Nullable private final Bson update; From 14bb86ef3b832c743962f3cb1cb2c565284e3ec6 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 10 Sep 2024 08:11:53 -0600 Subject: [PATCH 49/59] Improve code comments in `ClientBulkWriteOperation` JAVA-5528 --- .../internal/operation/ClientBulkWriteOperation.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index adf623ae491..fb2b1f95fbe 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -210,6 +210,10 @@ private Integer executeBatch( BatchEncoder batchEncoder = new BatchEncoder(); Supplier retryingBatchExecutor = decorateWriteWithRetries( retryState, operationContext, + // Each batch re-selects a server and re-checks out a connection because this is simpler, + // and it is allowed by https://jira.mongodb.org/browse/DRIVERS-2502. + // If connection pinning is required, {@code binding} handles that, + // and `ClientSession`, `TransactionContext` are aware of that. () -> withSourceAndConnection(binding::getWriteConnectionSource, true, (connectionSource, connection) -> { ConnectionDescription connectionDescription = connection.getDescription(); boolean effectiveRetryWrites = isRetryableWrite(retryWritesSetting, effectiveWriteConcern, connectionDescription, sessionContext); @@ -328,9 +332,6 @@ private BsonDocumentWrapper createBulkWriteCommand( final List unexecutedModels, final BatchEncoder batchEncoder, final Runnable ifCommandIsRetryable) { - // BULK-TODO This implementation must limit the number of `models` it includes in a batch if needed. - // Each batch re-selects a server and re-checks out a connection because this is simpler and it is allowed, - // see https://mongodb.slack.com/archives/C035ZJL6CQN/p1722265720037099?thread_ts=1722264610.664109&cid=C035ZJL6CQN. return new BsonDocumentWrapper<>( BULK_WRITE_COMMAND_NAME, new Encoder() { From f186b3126db19658af9392b4e0780b97030b15b7 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 16 Sep 2024 15:21:47 -0600 Subject: [PATCH 50/59] Fix `server-selection/logging/operation-id.json:Failed client bulkWrite operation: log messages have operationIds` JAVA-5528 --- .../server-selection/logging/operation-id.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json b/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json index c1024184ffd..72ebff60d80 100644 --- a/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json +++ b/driver-core/src/test/resources/unified-test-format/server-selection/logging/operation-id.json @@ -345,7 +345,7 @@ } }, { - "name": "bulkWrite", + "name": "clientBulkWrite", "object": "client", "arguments": { "models": [ From 3442a73fb4351ca373d1213e20f14cc5a1345a9a Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 17 Sep 2024 14:03:07 -0600 Subject: [PATCH 51/59] Rename an incorrectly named variable JAVA-5528 --- .../internal/operation/ClientBulkWriteOperation.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java index fb2b1f95fbe..b2f6b131723 100644 --- a/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java +++ b/driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java @@ -687,20 +687,20 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final Map insertModelDocumentIds = batchResult.getInsertModelDocumentIds(); for (BsonDocument individualOperationResponse : response.getCursorExhaust()) { int individualOperationIndexInBatch = individualOperationResponse.getInt32("idx").getValue(); - int writeModelIndexInBatch = batchStartModelIndex + individualOperationIndexInBatch; + int writeModelIndex = batchStartModelIndex + individualOperationIndexInBatch; if (individualOperationResponse.getNumber("ok").intValue() == 1) { assertTrue(verboseResultsSetting); - AbstractClientNamespacedWriteModel writeModel = getNamespacedModel(models, writeModelIndexInBatch); + AbstractClientNamespacedWriteModel writeModel = getNamespacedModel(models, writeModelIndex); if (writeModel instanceof ConcreteClientNamespacedInsertOneModel) { insertResults.put( - writeModelIndexInBatch, + writeModelIndex, new ConcreteClientInsertOneResult(insertModelDocumentIds.get(individualOperationIndexInBatch))); } else if (writeModel instanceof ConcreteClientNamespacedUpdateOneModel || writeModel instanceof ConcreteClientNamespacedUpdateManyModel || writeModel instanceof ConcreteClientNamespacedReplaceOneModel) { BsonDocument upsertedIdDocument = individualOperationResponse.getDocument("upserted", null); updateResults.put( - writeModelIndexInBatch, + writeModelIndex, new ConcreteClientUpdateResult( individualOperationResponse.getInt32("n").getValue(), individualOperationResponse.getInt32("nModified").getValue(), @@ -708,7 +708,7 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final } else if (writeModel instanceof ConcreteClientNamespacedDeleteOneModel || writeModel instanceof ConcreteClientNamespacedDeleteManyModel) { deleteResults.put( - writeModelIndexInBatch, + writeModelIndex, new ConcreteClientDeleteResult(individualOperationResponse.getInt32("n").getValue())); } else { fail(writeModel.getClass().toString()); @@ -718,7 +718,7 @@ ClientBulkWriteResult build(@Nullable final MongoException topLevelError, final individualOperationResponse.getInt32("code").getValue(), individualOperationResponse.getString("errmsg").getValue(), individualOperationResponse.getDocument("errInfo", new BsonDocument())); - writeErrors.put(writeModelIndexInBatch, individualOperationWriteError); + writeErrors.put(writeModelIndex, individualOperationWriteError); } } } From 3fc86bbabf1ba0fc9eb3adde26d6875ca83b1d41 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 17 Sep 2024 15:00:45 -0600 Subject: [PATCH 52/59] Stop linking to `Filters` from the documentation of `ClientNamespacedWriteModel.insertOne` JAVA-5527 --- .../mongodb/client/model/bulk/ClientNamespacedWriteModel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java index 448be5b06a3..5a2e0a672c4 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientNamespacedWriteModel.java @@ -53,7 +53,6 @@ public interface ClientNamespacedWriteModel { * @param document The document. * @return The requested {@link ClientNamespacedInsertOneModel}. * @param The document type, for example {@link Document}. - * @see Filters */ static ClientNamespacedInsertOneModel insertOne(final MongoNamespace namespace, final TDocument document) { notNull("namespace", namespace); From 86e5234ec8e7e04d77503c29402f46e55eea7166 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 18 Sep 2024 14:12:46 -0600 Subject: [PATCH 53/59] Update driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java Co-authored-by: Viacheslav Babanin --- .../com/mongodb/client/model/bulk/ClientBulkWriteResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java index c9a7cf4b403..c2bd603c3cc 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java @@ -35,7 +35,7 @@ @Evolving public interface ClientBulkWriteResult { /** - * Indicated whether this result was {@linkplain WriteConcern#isAcknowledged() acknowledged}. + * Indicates whether this result was {@linkplain WriteConcern#isAcknowledged() acknowledged}. * If not, then all other methods throw {@link UnsupportedOperationException}. * * @return Whether this result was acknowledged. From fb134f89cc9bc1754ac84d4c1d883669677f6fcc Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 18 Sep 2024 14:13:17 -0600 Subject: [PATCH 54/59] Update driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java Co-authored-by: Viacheslav Babanin --- .../main/com/mongodb/client/model/bulk/ClientDeleteResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java index 0ac0dcd8ab1..fcf66488114 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientDeleteResult.java @@ -20,7 +20,7 @@ /** * The result of a successful {@linkplain ClientNamespacedWriteModel individual delete operation}. - * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. + * Note that {@link WriteConcernError}s are not considered as making individual operations unsuccessful. * * @since 5.3 */ From a4bf4d0e0a9e0d1a841b6beeba19d0051b98e73b Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 18 Sep 2024 14:14:14 -0600 Subject: [PATCH 55/59] Fix typos in API docs JAVA-5527 --- .../com/mongodb/client/model/bulk/ClientInsertOneResult.java | 2 +- .../main/com/mongodb/client/model/bulk/ClientUpdateResult.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java index aa7641ed233..960078c6be5 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientInsertOneResult.java @@ -24,7 +24,7 @@ /** * The result of a successful {@linkplain ClientNamespacedWriteModel individual insert one operation}. - * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. + * Note that {@link WriteConcernError}s are not considered as making individual operations unsuccessful. * * @since 5.3 */ diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java index 447935290d4..c667db97c9e 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientUpdateResult.java @@ -23,7 +23,7 @@ /** * The result of a successful {@linkplain ClientNamespacedWriteModel individual update or replace operation}. - * Note that {@link WriteConcernError}s are not considered as making individuals operations unsuccessful. + * Note that {@link WriteConcernError}s are not considered as making individual operations unsuccessful. * * @since 5.3 */ From 2837235734a296bfc4d7a256906e46b8f9fd7a4c Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Wed, 18 Sep 2024 14:42:10 -0600 Subject: [PATCH 56/59] Change code to always refer to `ClientBulkWriteResult.Verbose` with the outer class name JAVA-5527 --- .../mongodb/client/model/bulk/ClientBulkWriteResult.java | 2 +- .../bulk/AcknowledgedSummaryClientBulkWriteResult.java | 2 +- .../bulk/AcknowledgedVerboseClientBulkWriteResult.java | 6 +++--- .../model/bulk/UnacknowledgedClientBulkWriteResult.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java index c2bd603c3cc..50437371982 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java @@ -89,7 +89,7 @@ public interface ClientBulkWriteResult { * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. * @see ClientBulkWriteOptions#verboseResults(Boolean) */ - Optional getVerbose(); + Optional getVerbose(); /** * The {@linkplain ClientBulkWriteResult#getVerbose() verbose results} of individual operations. diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java index bc72aaae52b..1bd18bd772f 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java @@ -76,7 +76,7 @@ public long getDeletedCount() { } @Override - public Optional getVerbose() { + public Optional getVerbose() { return empty(); } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java index a5c83b5825a..870e6d1dcdc 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -31,7 +31,7 @@ */ public final class AcknowledgedVerboseClientBulkWriteResult implements ClientBulkWriteResult { private final AcknowledgedSummaryClientBulkWriteResult summaryResults; - private final Verbose verbose; + private final AcknowledgedVerboseClientBulkWriteResult.Verbose verbose; public AcknowledgedVerboseClientBulkWriteResult( final AcknowledgedSummaryClientBulkWriteResult summaryResults, @@ -39,7 +39,7 @@ public AcknowledgedVerboseClientBulkWriteResult( final Map updateResults, final Map deleteResults) { this.summaryResults = summaryResults; - this.verbose = new Verbose(insertResults, updateResults, deleteResults); + this.verbose = new AcknowledgedVerboseClientBulkWriteResult.Verbose(insertResults, updateResults, deleteResults); } @Override @@ -146,7 +146,7 @@ public boolean equals(final Object o) { if (o == null || getClass() != o.getClass()) { return false; } - final Verbose verbose = (Verbose) o; + final AcknowledgedVerboseClientBulkWriteResult.Verbose verbose = (AcknowledgedVerboseClientBulkWriteResult.Verbose) o; return Objects.equals(insertResults, verbose.insertResults) && Objects.equals(updateResults, verbose.updateResults) && Objects.equals(deleteResults, verbose.deleteResults); diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java index 167385be1fc..29dfd1b07e2 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java @@ -61,7 +61,7 @@ public long getDeletedCount() throws UnsupportedOperationException { } @Override - public Optional getVerbose() throws UnsupportedOperationException { + public Optional getVerbose() throws UnsupportedOperationException { throw createUnacknowledgedResultsException(); } From b6702a6786b5cff6435a4b1d31be4ef29a723036 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Mon, 23 Sep 2024 12:06:51 -0600 Subject: [PATCH 57/59] Rename `ClientBulkWriteResult.Verbose` to `ClientBulkWriteResult.VerboseResults` JAVA-5527 --- .../com/mongodb/ClientBulkWriteException.java | 6 ++--- .../model/bulk/ClientBulkWriteOptions.java | 2 +- .../model/bulk/ClientBulkWriteResult.java | 6 ++--- ...nowledgedSummaryClientBulkWriteResult.java | 2 +- ...nowledgedVerboseClientBulkWriteResult.java | 27 ++++++++++--------- .../UnacknowledgedClientBulkWriteResult.java | 2 +- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index 04641b36173..cacf9eda521 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -118,9 +118,9 @@ public List getWriteConcernErrors() { * There are no guarantees on mutability or iteration order of the {@link Map} returned.

        * * @return The indexed {@link WriteError}s. - * @see ClientBulkWriteResult.Verbose#getInsertResults() - * @see ClientBulkWriteResult.Verbose#getUpdateResults() - * @see ClientBulkWriteResult.Verbose#getDeleteResults() + * @see ClientBulkWriteResult.VerboseResults#getInsertResults() + * @see ClientBulkWriteResult.VerboseResults#getUpdateResults() + * @see ClientBulkWriteResult.VerboseResults#getDeleteResults() */ public Map getWriteErrors() { return writeErrors; diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java index 10142f8aa15..942a37c43df 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteOptions.java @@ -79,7 +79,7 @@ static ClientBulkWriteOptions clientBulkWriteOptions() { ClientBulkWriteOptions comment(@Nullable BsonValue comment); /** - * Enables or disables requesting {@linkplain ClientBulkWriteResult#getVerbose() verbose results}. + * Enables or disables requesting {@linkplain ClientBulkWriteResult#getVerboseResults() verbose results}. * * @param verboseResults The flag specifying whether to request verbose results. * If {@code null}, the client defaults to {@code false}. diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java index 50437371982..50ccbda7d37 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java @@ -89,15 +89,15 @@ public interface ClientBulkWriteResult { * @throws UnsupportedOperationException If this result is not {@linkplain #isAcknowledged() acknowledged}. * @see ClientBulkWriteOptions#verboseResults(Boolean) */ - Optional getVerbose(); + Optional getVerboseResults(); /** - * The {@linkplain ClientBulkWriteResult#getVerbose() verbose results} of individual operations. + * The {@linkplain ClientBulkWriteResult#getVerboseResults() verbose results} of individual operations. * * @since 5.3 */ @Evolving - interface Verbose { + interface VerboseResults { /** * The indexed {@link ClientInsertOneResult}s. * The {@linkplain Map#keySet() keys} are the indexes of the corresponding {@link ClientNamespacedWriteModel}s diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java index 1bd18bd772f..fb088c662ae 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedSummaryClientBulkWriteResult.java @@ -76,7 +76,7 @@ public long getDeletedCount() { } @Override - public Optional getVerbose() { + public Optional getVerboseResults() { return empty(); } diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java index 870e6d1dcdc..14e9b016d07 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/AcknowledgedVerboseClientBulkWriteResult.java @@ -31,7 +31,7 @@ */ public final class AcknowledgedVerboseClientBulkWriteResult implements ClientBulkWriteResult { private final AcknowledgedSummaryClientBulkWriteResult summaryResults; - private final AcknowledgedVerboseClientBulkWriteResult.Verbose verbose; + private final AcknowledgedVerboseClientBulkWriteResult.VerboseResults verboseResults; public AcknowledgedVerboseClientBulkWriteResult( final AcknowledgedSummaryClientBulkWriteResult summaryResults, @@ -39,7 +39,7 @@ public AcknowledgedVerboseClientBulkWriteResult( final Map updateResults, final Map deleteResults) { this.summaryResults = summaryResults; - this.verbose = new AcknowledgedVerboseClientBulkWriteResult.Verbose(insertResults, updateResults, deleteResults); + this.verboseResults = new AcknowledgedVerboseClientBulkWriteResult.VerboseResults(insertResults, updateResults, deleteResults); } @Override @@ -73,8 +73,8 @@ public long getDeletedCount() { } @Override - public Optional getVerbose() { - return of(verbose); + public Optional getVerboseResults() { + return of(verboseResults); } @Override @@ -87,12 +87,12 @@ public boolean equals(final Object o) { } final AcknowledgedVerboseClientBulkWriteResult that = (AcknowledgedVerboseClientBulkWriteResult) o; return Objects.equals(summaryResults, that.summaryResults) - && Objects.equals(verbose, that.verbose); + && Objects.equals(verboseResults, that.verboseResults); } @Override public int hashCode() { - return Objects.hash(summaryResults, verbose); + return Objects.hash(summaryResults, verboseResults); } @Override @@ -103,18 +103,18 @@ public String toString() { + ", matchedCount=" + summaryResults.getMatchedCount() + ", modifiedCount=" + summaryResults.getModifiedCount() + ", deletedCount=" + summaryResults.getDeletedCount() - + ", insertResults=" + verbose.insertResults - + ", updateResults=" + verbose.updateResults - + ", deleteResults=" + verbose.deleteResults + + ", insertResults=" + verboseResults.insertResults + + ", updateResults=" + verboseResults.updateResults + + ", deleteResults=" + verboseResults.deleteResults + '}'; } - private static final class Verbose implements ClientBulkWriteResult.Verbose { + private static final class VerboseResults implements ClientBulkWriteResult.VerboseResults { private final Map insertResults; private final Map updateResults; private final Map deleteResults; - Verbose( + VerboseResults( final Map insertResults, final Map updateResults, final Map deleteResults) { @@ -146,7 +146,8 @@ public boolean equals(final Object o) { if (o == null || getClass() != o.getClass()) { return false; } - final AcknowledgedVerboseClientBulkWriteResult.Verbose verbose = (AcknowledgedVerboseClientBulkWriteResult.Verbose) o; + final AcknowledgedVerboseClientBulkWriteResult.VerboseResults verbose = + (AcknowledgedVerboseClientBulkWriteResult.VerboseResults) o; return Objects.equals(insertResults, verbose.insertResults) && Objects.equals(updateResults, verbose.updateResults) && Objects.equals(deleteResults, verbose.deleteResults); @@ -159,7 +160,7 @@ public int hashCode() { @Override public String toString() { - return "AcknowledgedVerboseClientBulkWriteResult.Verbose{" + return "AcknowledgedVerboseClientBulkWriteResult.VerboseResults{" + "insertResults=" + insertResults + ", updateResults=" + updateResults + ", deleteResults=" + deleteResults diff --git a/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java index 29dfd1b07e2..cdd649b3389 100644 --- a/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/internal/client/model/bulk/UnacknowledgedClientBulkWriteResult.java @@ -61,7 +61,7 @@ public long getDeletedCount() throws UnsupportedOperationException { } @Override - public Optional getVerbose() throws UnsupportedOperationException { + public Optional getVerboseResults() throws UnsupportedOperationException { throw createUnacknowledgedResultsException(); } From 24ce6db5f9dfd65766d31476281f01f24270e775 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 24 Sep 2024 03:30:47 -0600 Subject: [PATCH 58/59] Improve partial result API documentation wording JAVA-5527 DRIVERS-2975 --- .../src/main/com/mongodb/ClientBulkWriteException.java | 6 +++--- .../mongodb/client/model/bulk/ClientBulkWriteResult.java | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java index cacf9eda521..b964961d754 100644 --- a/driver-core/src/main/com/mongodb/ClientBulkWriteException.java +++ b/driver-core/src/main/com/mongodb/ClientBulkWriteException.java @@ -127,10 +127,10 @@ public Map getWriteErrors() { } /** - * The result of the successful part of a client-level bulk write operation. + * The result of the part of a client-level bulk write operation that is known to be successful. * - * @return The successful partial result. {@linkplain Optional#isPresent() Present} only if at least one - * {@linkplain ClientNamespacedWriteModel individual write operation} succeed. + * @return The successful partial result. {@linkplain Optional#isPresent() Present} only if the client received a response indicating success + * of at least one {@linkplain ClientNamespacedWriteModel individual write operation}. */ public Optional getPartialResult() { return ofNullable(partialResult); diff --git a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java index 50ccbda7d37..04257cb8460 100644 --- a/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java +++ b/driver-core/src/main/com/mongodb/client/model/bulk/ClientBulkWriteResult.java @@ -18,16 +18,15 @@ import com.mongodb.ClientBulkWriteException; import com.mongodb.WriteConcern; import com.mongodb.annotations.Evolving; -import com.mongodb.bulk.WriteConcernError; import java.util.Map; import java.util.Optional; /** * The result of a successful or partially successful client-level bulk write operation. - * Note that if only some of the {@linkplain ClientNamespacedWriteModel individual write operations} succeed, - * or if there are {@link WriteConcernError}s, then the successful partial result - * is still accessible via {@link ClientBulkWriteException#getPartialResult()}. + * Note that if a client-level bulk write operation fails while some of the + * {@linkplain ClientNamespacedWriteModel individual write operations} are known to be successful, + * then the successful partial result is still accessible via {@link ClientBulkWriteException#getPartialResult()}. * * @see ClientBulkWriteException * @since 5.3 From 6d8a3e632ebfdb711fa6be5211e155efa01e1d32 Mon Sep 17 00:00:00 2001 From: Valentin Kovalenko Date: Tue, 24 Sep 2024 03:57:24 -0600 Subject: [PATCH 59/59] Fixes after the merge JAVA-5528 --- .../src/test/functional/com/mongodb/client/CrudProseTest.java | 2 +- .../com/mongodb/client/unified/UnifiedCrudHelper.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java index 67790699f42..05dae50e563 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/CrudProseTest.java @@ -317,7 +317,7 @@ void insertMustGenerateIdAtMostOnce( (client, collection) -> client.bulkWrite( singletonList(insertOne(collection.getNamespace(), documentSupplier.get())), clientBulkWriteOptions().verboseResults(true)) - .getVerbose().orElseThrow(Assertions::fail).getInsertResults().get(0).getInsertedId().orElse(null)) + .getVerboseResults().orElseThrow(Assertions::fail).getInsertResults().get(0).getInsertedId().orElse(null)) ); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java index e8e427d0a04..03afe429cbc 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedCrudHelper.java @@ -1981,7 +1981,7 @@ static BsonDocument toMatchableValue(final ClientBulkWriteResult result) { .append("matchedCount", new BsonInt64(result.getMatchedCount())) .append("modifiedCount", new BsonInt64(result.getModifiedCount())) .append("deletedCount", new BsonInt64(result.getDeletedCount())); - result.getVerbose().ifPresent(verbose -> + result.getVerboseResults().ifPresent(verbose -> expected.append("insertResults", new BsonDocument(verbose.getInsertResults().entrySet().stream() .map(entry -> new BsonElement( entry.getKey().toString(),