Skip to content

docs: teach the WHERE form ladder in the skills and fix the Java joined-entity predicates - #363

Merged
zantvoort merged 1 commit into
mainfrom
docs/where-form-ladder
Aug 3, 2026
Merged

docs: teach the WHERE form ladder in the skills and fix the Java joined-entity predicates#363
zantvoort merged 1 commit into
mainfrom
docs/where-form-ladder

Conversation

@zantvoort

Copy link
Copy Markdown
Collaborator

Summary

The query skills now state a strict preference order for building WHERE clauses — always use the weakest form that compiles:

  1. where() — the default, typed to the root entity. Compound AND/OR conditions stay here via infix and/or (Kotlin); nested paths from the root are root-typed however deep, so navigating through a foreign key never forces an escalation.
  2. whereAny() — only for fields of explicitly joined (non-root) entities, which where() rejects at compile time.
  3. whereBuilder { } (Kotlin) / the where(it -> ...) lambda (Java) — only for what a plain predicate cannot express: EXISTS/NOT EXISTS or id/ref/record/template matching inside compound logic, plus AND/OR grouping in Java.

The Kotlin skill previously presented whereBuilder { } as the way to group AND/OR conditions, which steered generated code toward the heaviest form for clauses that plain where() with infix operators expresses directly.

Changes

  • storm-query-kotlin.md: replaced the "Compound Predicates (whereBuilder)" section with "Choosing the WHERE Form: where() → whereAny() → whereBuilder { }", including ✅/❌ examples, a genuine whereBuilder case (subquery composed into compound logic), and the note that consecutive where()/whereAny() calls AND together. Echoed the ladder in the infix-operator, joined-entity, and block-DSL sections; fixed an example that escalated a root path to orderByAny and an infix snippet typo.
  • storm-query-java.md: the same two preferences in Java terms (typed overloads over the lambda; it.where(...) over it.whereAny(...) inside it).
  • storm-rules.md: compact version of the rule so it is present even when only the rules skill is loaded.

Fix found while verifying

The Java QueryBuilder has no chained whereAny(path, operator, value) overload — generated metamodel paths are root-typed, so joined-entity predicates go through the where-lambda: .where(it -> it.whereAny(UserRole_.role, EQUALS, role)). The Java query skill (3 snippets) and the Java tabs of docs/first-query.md, docs/queries.md, and docs/relationships.md used the non-compiling chained form; all are corrected, with a one-sentence explanation added in queries.md.

Note: the docs fixes live in docs/ only, so they appear at /docs/next and reach the live /docs/* pages with the next release snapshot.

…ed-entity predicates

The query skills now state a strict preference order for building WHERE
clauses: where() first, whereAny() only for fields of joined (non-root)
entities, and the builder form last, reserved for conditions a plain
predicate cannot express. The Kotlin skill previously presented
whereBuilder { } as the way to group AND/OR conditions, which infix
and/or inside where() already covers.

Verifying the guidance against the API surfaced that the Java
QueryBuilder has no chained whereAny(path, operator, value) overload;
joined-entity predicates go through the where-lambda as
where(it -> it.whereAny(...)). The Java query skill and the Java tabs
of first-query, queries, and relationships used the non-compiling
chained form; all are corrected to the lambda form.
Copilot AI review requested due to automatic review settings August 3, 2026 10:15
@zantvoort
zantvoort merged commit 31e1aa4 into main Aug 3, 2026
8 checks passed
@zantvoort
zantvoort deleted the docs/where-form-ladder branch August 3, 2026 10:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Not ready to approve

Multiple updated skill examples use users.select() after previously defining users as a List<User>, so the snippets won’t compile as written.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR updates the Storm query documentation/skills to teach a strict “WHERE form ladder” (use the weakest form that compiles) and fixes several Java joined-entity predicate examples that previously used a non-existent chained whereAny(path, ...) overload.

Changes:

  • Reworked Kotlin and Java query skills to emphasize where()whereAny() → builder/lambda escalation rules (and similar guidance for orderBy/groupBy).
  • Corrected Java join filtering examples to use the where(it -> it.whereAny(...)) lambda form for joined-entity paths.
  • Added the condensed rule to storm-rules.md so it’s available via the rules skill.
File summaries
File Description
website/static/skills/storm-rules.md Adds a concise “WHERE ladder” rule to the rules skill.
website/static/skills/storm-query-kotlin.md Reframes WHERE guidance around an escalation ladder; updates examples and notes.
website/static/skills/storm-query-java.md Adds escalation preferences and fixes joined-entity predicate guidance/examples.
docs/relationships.md Fixes Java join filtering example to use the where-lambda + whereAny.
docs/queries.md Fixes Java join filtering example and adds a short explanation of the typing constraint.
docs/first-query.md Fixes Java join filtering example to use the where-lambda + whereAny.
Review details

Suppressed comments (3)

website/static/skills/storm-query-kotlin.md:469

  • This code block also uses users.select() without defining users in the snippet (and earlier users is a List result), so the example won’t compile as written. Start from orm.entity<User>() to keep the snippet standalone.
users.select()
    .whereBuilder {

website/static/skills/storm-query-java.md:397

  • Same issue as above: users is a List<User> in the earlier example, so users.select() in this snippet won’t compile. Start the chain from orm.entity(User.class) to keep the snippet standalone.
users.select()
    .innerJoin(UserRole.class).on(User.class)

website/static/skills/storm-query-java.md:415

  • This snippet also uses users.select() but users is a List<User> in the preceding example, so this won’t compile as written. Start from orm.entity(User.class) to avoid reusing the users list variable name.
users.select()
    .innerJoin(UserRole.class).on(User.class)
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Consecutive `where()`/`whereAny()` calls AND together (each clause parenthesized), so an AND of a root predicate and a joined-entity predicate needs no `whereBuilder` either — each clause sits on its own rung:

```kotlin
users.select()
Consecutive `where()` calls AND together (each clause parenthesized), so an AND of a root predicate and a joined-entity predicate is two calls, each in its weakest form — no single big lambda needed:

```java
users.select()
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.

2 participants