Skip to content

fix(facet): prevent int32 -1 facet_id sentinel collision with 1 - #3075

Open
Tyagiquamar wants to merge 1 commit into
typesense:v31from
Tyagiquamar:fix/int32-facet-sentinel-collision
Open

Tyagiquamar wants to merge 1 commit into
typesense:v31from
Tyagiquamar:fix/int32-facet-sentinel-collision

Conversation

@Tyagiquamar

Copy link
Copy Markdown

Change Summary

When an int32 facet value of -1 is indexed, its raw bitwise representation is 0xFFFFFFFF (UINT32_MAX).
In src/facet_index.cpp, facet_index_t::insert checked if(fvalue.facet_id == UINT32_MAX) to determine if a facet value omitted an explicit numerical facet ID (the pattern used by strings and int64). Because -1 matched UINT32_MAX, the facet index assigned facet_id = ++next_facet_id, assigning ID 1 to -1 when -1 was the first facet value indexed.
When a document with int32 value 1 was subsequently indexed, its facet ID was 1, causing fid_fvalues[1] to collide and label value 1 as "-1", merging both documents into a single facet bucket.

This change:

  • Adds an explicit has_explicit_facet_id boolean member to struct facet_value_id_t, initialized to true when constructed with a numerical ID (fid) and false when constructed with only a string value.
  • Updates facet_index_t::insert to check if(!fvalue.has_explicit_facet_id) instead of comparing against the in-band sentinel UINT32_MAX.
  • Adds a unit test in test/facet_index_test.cpp verifying that sequential insertion of int32 -1 and 1 preserves distinct facet IDs and labels.

fixes #3069

PR Checklist

When int32 facet value -1 is indexed, its bitwise uint32 representation is 0xFFFFFFFF (UINT32_MAX). Previously, facet_index_t::insert treated fvalue.facet_id == UINT32_MAX as an indicator that no explicit facet ID was provided, allocating ++next_facet_id (1). When a document with int32 value 1 was subsequently indexed, both values mapped to facet ID 1 in fid_fvalues, causing value 1 to be mislabeled as -1 and merging their counts into a single bucket.

Decouple explicit facet IDs from UINT32_MAX by introducing a has_explicit_facet_id flag on facet_value_id_t, and check !fvalue.has_explicit_facet_id in facet_index_t::insert. Add a regression test in test/facet_index_test.cpp.

Signed-off-by: Tyagiquamar <mohdquamartyagi@gmail.com>
@Tyagiquamar

Copy link
Copy Markdown
Author

Hi, just following up on this when you get a chance. The PR is ready from my side. Happy to make any changes if needed. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[30.2] int32 facet values -1 and 1 collide: filtered hits and facet labels disagree

1 participant