From efcf1ca5cdd55605ec3c1a763ff31c52d8e0bf01 Mon Sep 17 00:00:00 2001 From: Dmitry Kasimovskiy Date: Fri, 19 Jun 2026 12:30:16 +0300 Subject: [PATCH] fix(crud): inject default opts into varargs upsert The varargs \`upsert(Options, Object...)\` and \`upsertObject(Options, Object...)\` overloads forwarded their \`arguments\` straight to \`iprotoCall\`, producing a 3-arg wire call \`crud.upsert(space, tuple, operations)\` with no opts table. CRUD rock 1.5.0+ (bundled with Tarantool 3.5.0) rejects that 3-arg form at \`crud/compare/conditions.lua:93\` with \`ParseConditionError: Each condition should be table, got "string" (condition 1)\`. The 4-arg form \`(space, tuple, operations, opts)\` works because that overload delegates through \`toTupleOperationsOptsArgs\`. Fix: append \`DEFAULT_UPDATE_OPTIONS.getOptions()\` to the args when the caller has not already supplied an opts map (last varargs element not a \`Map\`). The guard preserves the existing 4-arg call from \`testUpsertParameters\`, which deliberately passes its own options map. Fixes \`TarantoolCrudClientTest#testUpsert\` on Tarantool 3.5.0. Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 4 ++++ .../client/factory/TarantoolCrudSpaceImpl.java | 14 ++++++++++++-- .../vshard_cluster/Dockerfile | 3 --- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c259d114..ffe013e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ - Upgrade TQE to v3.5.0. - Extract `ObjectMapper` to a static field in the test `tdg.Utils` helper to avoid recreating it on every `sendUsers`/`getUsers` call. +### Client + +- Append a default opts map to the varargs `upsert`/`upsertObject` calls so the request reaches the CRUD rock as the 4-arg form; CRUD 1.5.0+'s conditions parser rejects the legacy 3-arg form with `ParseConditionError`. + ### Documentation - Document supported Java types for Tarantool data mapping in `tuple_pojo_mapping` docs (RU/EN), including Tarantool extension types (`decimal`, `uuid`, `datetime`, `interval`, `tuple`) and related mapping notes. diff --git a/tarantool-client/src/main/java/io/tarantool/client/factory/TarantoolCrudSpaceImpl.java b/tarantool-client/src/main/java/io/tarantool/client/factory/TarantoolCrudSpaceImpl.java index 7a792e89..c4df22f3 100644 --- a/tarantool-client/src/main/java/io/tarantool/client/factory/TarantoolCrudSpaceImpl.java +++ b/tarantool-client/src/main/java/io/tarantool/client/factory/TarantoolCrudSpaceImpl.java @@ -726,12 +726,14 @@ public CompletableFuture> update( @Override public CompletableFuture upsert(Options options, Object... arguments) { - return crudCallSingleResult(options, CRUD_UPSERT, arguments).thenAccept((r) -> {}); + Object[] args = ensureOpts(arguments, DEFAULT_UPDATE_OPTIONS.getOptions()); + return crudCallSingleResult(options, CRUD_UPSERT, args).thenAccept((r) -> {}); } @Override public CompletableFuture upsertObject(Options options, Object... arguments) { - return crudCallSingleResult(options, CRUD_UPSERT_OBJECT, arguments).thenAccept((r) -> {}); + Object[] args = ensureOpts(arguments, DEFAULT_UPDATE_OPTIONS.getOptions()); + return crudCallSingleResult(options, CRUD_UPSERT_OBJECT, args).thenAccept((r) -> {}); } @Override @@ -897,6 +899,14 @@ private Object[] toTupleOperationsOptsArgs( return new Object[] {tuple, operations, options.getOptions()}; } + // CRUD 1.5.0+ needs an opts table; append a default one when the caller didn't supply it. + private static Object[] ensureOpts(Object[] args, Map defaultOpts) { + if (args.length > 0 && args[args.length - 1] instanceof Map) return args; + Object[] withOpts = Arrays.copyOf(args, args.length + 1); + withOpts[args.length] = defaultOpts; + return withOpts; + } + /** * Converts key, operations and options to array of arguments. * diff --git a/tarantool-shared-resources/vshard_cluster/Dockerfile b/tarantool-shared-resources/vshard_cluster/Dockerfile index 3d43922e..64ec1af4 100644 --- a/tarantool-shared-resources/vshard_cluster/Dockerfile +++ b/tarantool-shared-resources/vshard_cluster/Dockerfile @@ -13,9 +13,6 @@ WORKDIR "$TARANTOOL_WORKDIR/$APP_NAME" RUN mkdir -p /etc/tarantool/instances.enabled && \ ln -s "$TARANTOOL_WORKDIR/$APP_NAME" /etc/tarantool/instances.enabled/app -RUN sed -i 's|http://archive.ubuntu.com/ubuntu/|http://mirror.yandex.ru/ubuntu/|g; s|http://security.ubuntu.com/ubuntu/|http://mirror.yandex.ru/ubuntu/|g' /etc/apt/sources.list - -# install dependencies RUN apt-get -y update && \ apt-get -y install build-essential cmake make gcc git unzip && \ apt-get -y clean