diff --git a/src/t_set.c b/src/t_set.c index 7522a68cf..f679676c2 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -1859,8 +1859,7 @@ void sunionCommand(client *c) { void sunioncardCommand(client *c) { long j; long numkeys = 0; - long limit = 0; - int have_limit = 0; + long limit = 0; /* 0 means no limit. */ int approx = 0; if (getRangeLongFromObjectOrReply(c, c->argv[1], 1, LONG_MAX, @@ -1880,7 +1879,6 @@ void sunioncardCommand(client *c) { if (getPositiveLongFromObjectOrReply(c, c->argv[j], &limit, "LIMIT can't be negative") != C_OK) return; - have_limit = 1; } else if (!strcasecmp(opt, "APPROX")) { approx = 1; } else { @@ -1889,11 +1887,6 @@ void sunioncardCommand(client *c) { } } - if (have_limit && limit == 0) { - addReplyLongLong(c, 0); - return; - } - if (approx) { /* HLL-based approximate cardinality: use a temporary HLL object * with the standard sparse→dense encoding (same as PFADD). */ @@ -1938,7 +1931,7 @@ void sunioncardCommand(client *c) { } elements_processed++; - if (have_limit && + if (limit > 0 && (elements_processed % HLL_APPROX_CHECK_INTERVAL == 0)) { uint64_t est = hllCount(hllobj->ptr, NULL); if (est >= (uint64_t)limit) { @@ -1951,7 +1944,7 @@ void sunioncardCommand(client *c) { } uint64_t cardinality = hllCount(hllobj->ptr, NULL); - if (have_limit && cardinality > (uint64_t)limit) + if (limit > 0 && cardinality > (uint64_t)limit) cardinality = (uint64_t)limit; if (server.memory_tracking_enabled) { diff --git a/tests/unit/type/set.tcl b/tests/unit/type/set.tcl index 8480757da..ba92800b8 100644 --- a/tests/unit/type/set.tcl +++ b/tests/unit/type/set.tcl @@ -306,11 +306,11 @@ foreach type {single multiple single_multiple} { assert_equal $exact $approx } - test "SUNIONCARD LIMIT 0 returns 0 immediately" { + test "SUNIONCARD LIMIT 0 means no limit" { r del set1{t} set2{t} r sadd set1{t} a b c r sadd set2{t} c d e - assert_equal 0 [r sunioncard 2 set1{t} set2{t} LIMIT 0] + assert_equal 5 [r sunioncard 2 set1{t} set2{t} LIMIT 0] } test "SUNIONCARD with both APPROX and LIMIT" { @@ -318,7 +318,7 @@ foreach type {single multiple single_multiple} { r sadd set1{t} a b c r sadd set2{t} c d e assert_equal 3 [r sunioncard 2 set1{t} set2{t} APPROX LIMIT 3] - assert_equal 0 [r sunioncard 2 set1{t} set2{t} APPROX LIMIT 0] + assert_equal 5 [r sunioncard 2 set1{t} set2{t} APPROX LIMIT 0] } test "SUNIONCARD APPROX with large sets is within HLL error margin" { @@ -421,7 +421,7 @@ foreach type {single multiple single_multiple} { test "SUNIONCARD with two sets - $type" { set expected [llength [lsort -uniq "[r smembers set1{t}] [r smembers set2{t}]"]] assert_equal $expected [r sunioncard 2 set1{t} set2{t}] - assert_equal 0 [r sunioncard 2 set1{t} set2{t} LIMIT 0] + assert_equal $expected [r sunioncard 2 set1{t} set2{t} LIMIT 0] assert_equal 3 [r sunioncard 2 set1{t} set2{t} LIMIT 3] assert_equal $expected [r sunioncard 2 set1{t} set2{t} LIMIT 10000] } @@ -429,7 +429,7 @@ foreach type {single multiple single_multiple} { test "SUNIONCARD against three sets - $type" { set expected [llength [lsort -uniq "[r smembers set1{t}] [r smembers set2{t}] [r smembers set3{t}]"]] assert_equal $expected [r sunioncard 3 set1{t} set2{t} set3{t}] - assert_equal 0 [r sunioncard 3 set1{t} set2{t} set3{t} LIMIT 0] + assert_equal $expected [r sunioncard 3 set1{t} set2{t} set3{t} LIMIT 0] assert_equal 2 [r sunioncard 3 set1{t} set2{t} set3{t} LIMIT 2] assert_equal $expected [r sunioncard 3 set1{t} set2{t} set3{t} LIMIT 10000] } @@ -447,7 +447,8 @@ foreach type {single multiple single_multiple} { } test "SUNIONCARD APPROX with LIMIT - $type" { - assert_equal 0 [r sunioncard 2 set1{t} set2{t} APPROX LIMIT 0] + set approx_no_limit [r sunioncard 2 set1{t} set2{t} APPROX] + assert_equal $approx_no_limit [r sunioncard 2 set1{t} set2{t} APPROX LIMIT 0] assert_equal 10 [r sunioncard 2 set1{t} set2{t} APPROX LIMIT 10] }