diff --git a/CHANGELOG.md b/CHANGELOG.md index 318cdea10..d234e683b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Fixed `JobListParams.Where` writing into the first `NamedArgs` it's given when merging multiple sets of named arguments, which could leak arguments into a map the caller reused for another query. It also no longer panics when the first set is `nil`. [PR #1575](https://github.com/riverqueue/river/pull/1575). + ## [0.51.1] - 2026-11-05 ### Fixed diff --git a/job_list_params.go b/job_list_params.go index bddd1be0c..a42bbe9c9 100644 --- a/job_list_params.go +++ b/job_list_params.go @@ -576,14 +576,11 @@ func (p *JobListParams) Where(sql string, namedArgsMany ...NamedArgs) *JobListPa paramsCopy := p.copy() var allNamedArgs NamedArgs - if len(namedArgsMany) > 0 { - for i, namedArgs := range namedArgsMany { - if i == 0 { - allNamedArgs = namedArgs - } else { - maps.Copy(allNamedArgs, namedArgs) - } + for _, namedArgs := range namedArgsMany { + if allNamedArgs == nil { + allNamedArgs = make(NamedArgs, len(namedArgs)) } + maps.Copy(allNamedArgs, namedArgs) } paramsCopy.where = append(paramsCopy.where, dblist.WherePredicate{NamedArgs: allNamedArgs, SQL: sql}) diff --git a/job_list_params_test.go b/job_list_params_test.go index e964a5975..0e741ed39 100644 --- a/job_list_params_test.go +++ b/job_list_params_test.go @@ -636,3 +636,28 @@ func Test_JobListParams_toDBParamsWithoutFinalizedIndex(t *testing.T) { }) } } + +func TestJobListParams_Where(t *testing.T) { + t.Parallel() + + t.Run("MergesNamedArgsWithoutMutatingThem", func(t *testing.T) { + t.Parallel() + + var ( + namedArgs1 = NamedArgs{"a": 1, "b": 2} + namedArgs2 = NamedArgs{"b": 3} + ) + + params := NewJobListParams().Where("a = @a AND b = @b", namedArgs1, namedArgs2) + require.Equal(t, map[string]any{"a": 1, "b": 3}, params.where[0].NamedArgs) + require.Equal(t, NamedArgs{"a": 1, "b": 2}, namedArgs1) + require.Equal(t, NamedArgs{"b": 3}, namedArgs2) + }) + + t.Run("NilFirstNamedArgs", func(t *testing.T) { + t.Parallel() + + params := NewJobListParams().Where("a = @a", nil, NamedArgs{"a": 1}) + require.Equal(t, map[string]any{"a": 1}, params.where[0].NamedArgs) + }) +}