Skip to content

[OPIK-6884] [BE] refactor: SELECT DISTINCT trace_id in dataset-item filter-gate bounds#7418

Merged
thiagohora merged 1 commit into
mainfrom
thiagoh/OPIK-6884-distinct-trace-id-gate-bounds
Jul 10, 2026
Merged

[OPIK-6884] [BE] refactor: SELECT DISTINCT trace_id in dataset-item filter-gate bounds#7418
thiagohora merged 1 commit into
mainfrom
thiagoh/OPIK-6884-distinct-trace-id-gate-bounds

Conversation

@thiagohora

Copy link
Copy Markdown
Contributor

Details

Follow-up to the merged #7412, addressing @andrescrz's review nit: "Minor: I believe better with distinct trace_id for both cases. Applies to the changes below as well."

The DatasetItemDAO experiment-item filter gates (count query and stats query) added in #7412 bound the traces scan by the experiment trace-id set:

AND id IN (SELECT trace_id FROM experiment_items WHERE workspace_id = :workspace_id ...)
AND project_id IN (SELECT DISTINCT project_id FROM traces WHERE ... id IN (SELECT trace_id FROM experiment_items ...))

experiment_items holds one row per (experiment, dataset item), so a trace referenced by multiple items appears multiple times. This changes those four gate subqueries to SELECT DISTINCT trace_id, deduplicating the id set before it feeds the IN (...) bound (and the nested project-resolution). DISTINCT inside an IN (...) is result-equivalent — set membership is unchanged — so query results are identical; it only yields a smaller prepared set.

Change checklist

  • User facing
  • Documentation update

Issues

  • OPIK-6884 (rolling story; full-scan audit follow-up)

AI-WATERMARK

AI-WATERMARK: yes

  • Tools: Claude Code
  • Model(s): Claude Opus 4.8
  • Scope: applied the DISTINCT trace_id review suggestion to the four gate subqueries and authored this PR description.
  • Human verification: Author reviewed the change; mvn spotless:check compile runs clean locally.

Testing

Documentation

No user-facing or SDK changes; internal query-path hardening only.

Review (andrescrz): dedupe the trace-id set in the gate bounds and their
project-resolution subqueries. DISTINCT inside an IN(...) is result-equivalent
(membership is unchanged) but yields a smaller prepared set.
@thiagohora thiagohora requested a review from a team as a code owner July 9, 2026 15:58
@github-actions github-actions Bot added java Pull requests that update Java code Backend labels Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

⏱️ pre-commit per-hook timing

Hook Description Result Duration
☕ spotless — java backend Format Java code 7.69s
Total (1 ran) 7.69s
⏭️ 40 skipped (no matching files changed)
Hook Description Result
🐍 trim trailing whitespace — python sdk Strip trailing whitespace ⏭️
🐍 fix end of files — python sdk Ensure files end in a newline ⏭️
🐍 ruff — python sdk Lint + autofix Python (ruff) ⏭️
🐍 ruff-format — python sdk Format Python code (ruff) ⏭️
🐍 mypy — python sdk Static type check ⏭️
🤖 trim trailing whitespace — optimizer Strip trailing whitespace ⏭️
🤖 fix end of files — optimizer Ensure files end in a newline ⏭️
🤖 check yaml — optimizer Validate YAML syntax ⏭️
🤖 check json — optimizer Validate JSON syntax ⏭️
🤖 check toml — optimizer Validate TOML syntax ⏭️
🤖 check for added large files — optimizer Block large files (>1MB) ⏭️
🔐 detect private key — optimizer Block committed private keys ⏭️
🤖 check for merge conflicts — optimizer Block merge-conflict markers ⏭️
🤖 check for case conflicts — optimizer Block case-only name clashes ⏭️
🤖 pyupgrade — optimizer Modernize Python syntax ⏭️
🤖 ruff — optimizer Lint + autofix Python (ruff) ⏭️
🤖 ruff-format — optimizer Format Python code (ruff) ⏭️
🤖 mypy — optimizer Static type check ⏭️
📓 nbstripout — optimizer notebooks Strip notebook output ⏭️
📝 markdownlint — optimizer Lint Markdown ⏭️
🔤 codespell — optimizer Fix common misspellings ⏭️
📊 radon cc — optimizer Cyclomatic-complexity gate ⏭️
📊 radon raw — optimizer Raw size metrics gate ⏭️
📊 xenon — optimizer Fail on complexity thresholds ⏭️
📊 lizard — optimizer Cyclomatic-complexity gate ⏭️
🧹 vulture — optimizer Find dead code ⏭️
🛡️ trim trailing whitespace — guardrails Strip trailing whitespace ⏭️
🛡️ fix end of files — guardrails Ensure files end in a newline ⏭️
🛡️ ruff — guardrails Lint + autofix Python (ruff) ⏭️
🛡️ ruff-format — guardrails Format Python code (ruff) ⏭️
🛡️ mypy — guardrails Static type check ⏭️
⚓ helm-docs Regenerate Helm chart README ⏭️
block non-public FE plugins Block non-public FE plugins ⏭️
🧪 pre-commit wrapper smoke tests Self-test the wrapper scripts ⏭️
🌐 eslint — frontend Lint + autofix JS/TS ⏭️
🌐 typecheck — frontend Whole-project tsc type check ⏭️
📘 eslint — typescript sdk Lint + autofix JS/TS ⏭️
📘 typecheck — typescript sdk Whole-project tsc type check ⏭️
⚙️ actionlint — github workflows Lint GitHub Actions workflows ⏭️
🐳 hadolint — dockerfiles Lint Dockerfiles ⏭️

@thiagohora thiagohora requested a review from andrescrz July 9, 2026 16:02
Comment on lines +351 to +352
AND id IN (SELECT DISTINCT trace_id FROM experiment_items WHERE workspace_id = :workspace_id AND experiment_id IN :experimentIds)
AND project_id IN (SELECT DISTINCT project_id FROM traces WHERE workspace_id = :workspace_id AND id IN (SELECT DISTINCT trace_id FROM experiment_items WHERE workspace_id = :workspace_id AND experiment_id IN :experimentIds))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CamelCase ClickHouse binds violate rule

:.agents/skills/opik-backend/clickhouse.md requires ClickHouse parameter names to be snake_case, but this query path still uses :experimentIds in the placeholder and bind sites, so it stays non-compliant — should we rename them to experiment_ids here and in the updated stats query too?

Severity

Want Baz to fix this for you? Activate Fixer You can also update your AI coding guidelines based on this comment by apply pr to [branch name]

Other fix methods

Fix in Cursor

Prompt for AI Agents
Before applying, verify this suggestion against the current code. In
apps/opik-backend/src/main/java/com/comet/opik/domain/DatasetItemDAO.java around lines
351-352 inside the SQL template SELECT_DATASET_ITEMS_WITH_EXPERIMENT_ITEMS_COUNT, the
added trace gate filters still reference :experimentIds (camelCase). Refactor this hunk
to use the snake_case ClickHouse placeholder :experiment_ids and then update all
corresponding bind sites in the Java methods that execute this query (e.g.,
getItems/getCount) to bind the parameter under the same name (experiment_ids) instead of
experimentIds. Also apply the same rename in
SELECT_DATASET_ITEMS_WITH_EXPERIMENT_ITEMS_STATS around lines 853-854 where the same
subquery pattern repeats, ensuring its execution path binds experiment_ids consistently.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a nit from Baz, but valid. Optionally fee free to address it.

@andrescrz andrescrz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Comment on lines +351 to +352
AND id IN (SELECT DISTINCT trace_id FROM experiment_items WHERE workspace_id = :workspace_id AND experiment_id IN :experimentIds)
AND project_id IN (SELECT DISTINCT project_id FROM traces WHERE workspace_id = :workspace_id AND id IN (SELECT DISTINCT trace_id FROM experiment_items WHERE workspace_id = :workspace_id AND experiment_id IN :experimentIds))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a nit from Baz, but valid. Optionally fee free to address it.

@thiagohora thiagohora merged commit 285ddb6 into main Jul 10, 2026
70 checks passed
@thiagohora thiagohora deleted the thiagoh/OPIK-6884-distinct-trace-id-gate-bounds branch July 10, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend java Pull requests that update Java code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants