Repository navigation
Fix FTSearchParams.params(Map) dropping values when parameters are already set - #4677
Conversation
The merge branch of params(Map) called this.params.putAll(params), copying the field onto itself instead of merging the paramValues argument. When parameters were already present (e.g. addParam followed by params(map), or a second params(map) call) the supplied values were silently discarded and never emitted in the PARAMS clause, so the corresponding $name placeholders in an FT.SEARCH query were not substituted. Use the paramValues argument. Add FTSearchParamsTest covering the merge path.
kdelay
left a comment
There was a problem hiding this comment.
The one-line fix looks correct: in the merge branch params resolves to the field, so this.params.putAll(params) was a self-copy and the argument was discarded. I grepped the rest of src/main/java for the same shape and this is the only occurrence — the other putAll hits are the JedisByteMap/JedisByteHashMap overrides and the executor map aggregators, so it is a one-off rather than a pattern.
Two notes on the test. I ran mvn -B -Dwith-param-names=true -Dtest=FTSearchParamsTest -DfailIfNoTests=false test on a clean checkout of master with this PR applied (Corretto 17): 1 test, 0 failures. Reverting only the production line reproduces the failure, with the emitted args being [FT.SEARCH, PARAMS, 2, existing, 1].
-
Notice that the expected
2in that assertion is satisfied by thePARAMSarity token, not by the value ofadded—containsArgumentsis presence-only and position-agnostic, so the only thing actually catching the regression is theaddedkey. That also means the arity, which is the part the server parses, is never asserted. To check how much that costs, I mutated line 146 toargs.add(PARAMS).add(params.size())(arity 2 instead of 4 for two parameters, which the server would reject) and re-ran the same command: still 1 test, 0 failures. AnassertThat(args, hasArgument(2, RawableFactory.from(4)))alongside the existing assertion would pin the pair count and make the test fail on that class of change too. -
The description names two ways into the merge branch —
addParamthenparams(map), and twoparams(map)calls — but only the first is covered. The second one is a couple of extra lines in the same test and is the path a caller building a query from several maps would hit.
Unrelated to this PR, but adjacent enough to be worth a separate issue: AggregationBuilder.params(Map) appends the PARAMS clause into aggrArgs eagerly instead of accumulating into a map, so a second call emits a second clause rather than merging. Built with the same style of unit check, new AggregationBuilder("*").params({one=1}).params({two=2}) produces FT.AGGREGATE * PARAMS 2 one 1 PARAMS 2 two 2. Different failure mode from this one (duplicate clause instead of dropped values), same API shape.
One practical note if you touch the test: formatter-maven-plugin:validate runs before test, so an unformatted new file fails the build before any test executes.
…e path containsArguments is presence-only, so the original assertion caught the dropped value only through the parameter name; the PARAMS arity token, which is the part the server parses, was never asserted. Pin it with hasArgument(2, ...) so a wrong count is caught as well. Also cover the other way into the merge branch, two params(map) calls, alongside the addParam-then-params(map) case.
|
Thanks, both are good catches. Done in ac375f7.
Verification (Docker, temurin-17, On |
Strip bug-history comments from FTSearchParamsTest; the test names carry the information. Document merge and duplicate-name semantics on addParam and params(Map), which had no javadoc. Add an integration test mixing addParam with params(Map) - the merge branch fixed by this PR had no live-server coverage.
Group the merge regression tests under a nested AddParamsTests class, matching the structure used by HotkeysParamsTest, IncrexParamsTest and TSRangeParamsTest (Equality/Validation/Builder/AddParams groups), so future coverage slots in without reshuffling. Note the expected wire shape per test.
A name set via addParam and again via params(Map), in either order, keeps the later value - the behavior the new javadoc documents. The PARAMS arity of 2 proves a single pair is emitted.
|
@HDPark95 Good catch — the merge branch has been a self- To get this release-ready in one pass, I pushed a few small commits to your branch:
One ask for future contributions: when fixing a bug like this, please start with an actual usage pattern that demonstrates the issue on a real server — ideally, a small integration test (they are fast with our dockerized setup; see Thanks again! |
|
Thanks for the cleanups and the javadoc. The restructured test reads better, and the integration test on the mixed Point taken on leading with an integration test. I went through |
What
FTSearchParams.params(Map<String, Object> paramValues)is meant to merge thegiven values into any parameters already set. The merge branch copies the field
onto itself instead of the argument:
paramshere resolves to the field, sothis.params.putAll(params)isthis.params.putAll(this.params)— a no-op, and the suppliedparamValuesaredropped.
Impact
Whenever parameters are already present — e.g.
addParam(...)followed byparams(map), or twoparams(map)calls — the second map is silentlydiscarded. Those values never reach the wire (the
PARAMSclause omits them),so an
FT.SEARCHquery that references the corresponding$nameplaceholdersdoes not get them substituted. When the parameter map starts empty the first
branch is taken and the value is preserved, which is why this went unnoticed.
Fix
Use the
paramValuesargument in the merge branch.Test
Added
FTSearchParamsTest.paramsMapMergesInsteadOfDroppingValues, a server-freeunit test that sets one parameter via
addParam, then merges a second viaparams(Map), and asserts both are emitted in the built command arguments. Itfails on the current code and passes with the fix.
Note
Low Risk
Small, localized fix to RediSearch query parameter assembly with dedicated unit and integration tests; no auth or data-path changes beyond correct PARAMS emission.
Overview
Fixes
FTSearchParams.params(Map)so a second map actually merges when parameters already exist (e.g. afteraddParamor an earlierparamscall). The merge branch incorrectly calledputAllon the internal map with itself, so extraparamValueswere dropped and never appeared in thePARAMSclause forFT.SEARCH.Documents merge/overwrite behavior on
addParamandparams. Adds unit tests inFTSearchParamsTestand an integration testtestQueryParamsMixedAddParamAndMapfor mixedaddParam+paramsusage.Reviewed by Cursor Bugbot for commit 7500187. Bugbot is set up for automated code reviews on this repo. Configure here.