Exclusion filter GraphQL descriptions do not mention that NULL rows are dropped
Problem
https://gitlab.com/gitlab-org/gitlab/-/issues/629296 added 27 *Not GraphQL arguments across the eight analytics aggregation engines. ClickHouse evaluates NULL NOT IN (...) as NULL, and WHERE/HAVING treat NULL as false, so an exclusion filter also drops rows whose filtered column is NULL. This was verified by measurement: three pipelines with user_id of 1, 2, and NULL, filtered with user_id_not: [1], return 1 row instead of 2.
Consequence for API consumers: userId: [X] and userIdNot: [X] do not sum to the unfiltered total.
The behavior is documented for developers, in doc/development/aggregation_engines.md and in the filter class itself, but the generated GraphQL reference that API consumers actually read says only, e.g., "Negative filter by one or many user Global IDs."
Columns affected, because they are nullable: pipelines.user_id, pipelines.ref, pipelines.source, deployments.user_id, merge_requests.author_id, duo_workflows.project_id, ai_usage_events.feature, ai_usage_events.flow_type. The remaining filters are on non-nullable columns and are unaffected.
Two cases are the most misleading, because NULL is the normal value rather than an edge case:
ai_usage_events.flow_typeisnullIf(JSONExtractString(extras, 'flow_type'), ''), NULL for every non-Duo-Agent-Platform event.ai_usage_events.featureis aCASE ... ELSE NULL END, NULL for any event outside the registered feature list.
So flowTypeNot: ["x"] returns only Duo Agent Platform events.
Proposal
Add the NULL caveat to the generated argument description. Descriptions are built in one place, lib/gitlab/database/aggregation/graphql/adapter.rb, so a single change covers all 27 *Not arguments.
Decide this together with the open wording discussion on !256159 (merged), which covers the same generated strings — current output is "Negative filter by ...", with "Exclude ..." proposed as an alternative.
Out of scope
- Changing the NULL semantics themselves, e.g. wrapping the predicate in
ifNull. - Adding request-level validation of unrecognized filter values (tracked separately).