Polymorphic SOQL with TYPEOF: querying Task.WhatId, Task.WhoId, ContentDocumentLink.LinkedEntityId, FeedItem.ParentId; fallback to Type filters; indexing and selectivity. NOT for subqueries or dot-notation traversal — use apex/apex-soql-relationship-queries. NOT for the Activity data model — use admin/activity-and-task-patterns.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add PranavNagrecha/AwesomeSalesforceSkills --skill apex-polymorphic-soql --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Apex Polymorphic Soql?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/pranavnagrecha-apex-polymorphic-soql)More formats (shields.io, HTML) on the badges page.
---
name: apex-polymorphic-soql
description: "Polymorphic SOQL with TYPEOF: querying Task.WhatId, Task.WhoId, ContentDocumentLink.LinkedEntityId, FeedItem.ParentId; fallback to Type filters; indexing and selectivity. NOT for subqueries or dot-notation traversal — use apex/apex-soql-relationship-queries. NOT for the Activity data model — use admin/activity-and-task-patterns."
category: apex
salesforce-version: "Spring '25+"
well-architected-pillars:
- Performance
- Reliability
tags:
- apex
- soql
- typeof
- polymorphic
- whatid
- linkedentityid
triggers:
- "soql typeof what when account opportunity"
- "polymorphic lookup query salesforce what.name fails"
- "contentdocumentlink linkedentityid polymorphic query"
- "typeof where clause syntax soql"
- "polymorphic id type filter what.type"
- "apex query all attachments across object types"
- "soql typeof polymorphic what who task query"
inputs:
- Polymorphic field and its possible target objects
- Fields needed per target type
- Selectivity / index requirements
outputs:
- TYPEOF query template
- Type-filtered fallback queries
- Indexing strategy for polymorphic filters
dependencies: []
version: 1.0.0
author: Pranav Nagrecha
updated: 2026-04-21
status: stub
---
# Apex Polymorphic SOQL
Activate when writing SOQL against polymorphic fields — `Task.WhatId`, `Task.WhoId`, `Event.WhatId`, `ContentDocumentLink.LinkedEntityId`, `FeedItem.ParentId`, `Note.ParentId`. Polymorphic fields reference multiple object types; field access requires `TYPEOF` or `Type` filters, and the platform's indexing rules are different from normal lookup fields.
## Before Starting
- **Know which fields are polymorphic.** Not many: Task/Event WhatId/WhoId, ContentDocumentLink.LinkedEntityId, FeedItem.ParentId, Note.ParentId, EmailMessageRelation.RelationId, a few others.
- **Decide: TYPEOF or Type filter?** TYPEOF returns per-type projected fields in one query. `WhereType` filter narrows to one type then accesses its fields normally.
- **Plan selectivity.** `WhatId = :id` is selective; `What.Type = 'Account'` is a filter, not an index.
## Core Concepts
### TYPEOF syntax
```
SELECT Id, Subject,
TYPEOF What
WHEN Account THEN Name, Industry
WHEN Opportunity THEN Amount, StageName
ELSE Name
END
FROM Task
WHERE ActivityDate = TODAY
```
Per-row, the query returns fields of the matched target type. `ELSE` is optional — include it to cover unmatched cases.
### Type filter fallback
```
SELECT Id, What.Name FROM Task WHERE What.Type = 'Account'
```
Post-filter, `What.Name` is safe because every match is an Account. Less flexible than TYPEOF but simpler.
### Common polymorphic fields
- `Task.WhatId` — Account, Opportunity, custom, ...
- `Task.WhoId` — Contact or Lead
- `ContentDocumentLink.LinkedEntityId` — any object with content enabled
- `FeedItem.ParentId` — any feed-enabled object
- `Note.ParentId` / `NoteAndAttachment.ParentId` — legacy
### Indexing
Polymorphic field equality on Id is selective (indexed). Filtering on `.Type` is a non-indexed filter — apply after an Id-selective filter.
## Common Patterns
### Pattern: TYPEOF with common-parent field
```
SELECT Id, Subject, What.Name, What.Type FROM Task WHERE Id IN :ids
```
`What.Name` works because Name is on every polymorphic target's parent. Avoids TYPEOF ceremony for common fields.
### Pattern: TYPEOF for type-specific fields
Use when you need Industry (Account), Amount (Opportunity), etc. Only TYPEOF can project per-type fields.
### Pattern: Two-step query
Query IDs and types; partition; re-query per type with full field lists. Useful when downstream logic per type is complex.
## Decision Guidance
| Need | Pattern |
|---|---|
| Just Id, Type, Name | Flat query with `What.Name` |
| Per-type fields in one pass | TYPEOF WHEN |
| One specific type only | `WHERE What.Type = 'Account'` |
| Complex per-type processing | Query once, partition in Apex, re-query per type |
## Recommended Workflow
1. Identify the polymorphic field and its possible target objects.
2. Decide per-type fields required.
3. If varied per type, use TYPEOF; if one type only, use Type filter.
4. Ensure Id or other selective filter is present — Type alone is non-selective.
5. Apex-side: iterate results and use `instanceof` or `.getSObjectType()` to dispatch.
6. Test with rows of each target type present.
7. Measure query plan if performance-critical.
## Review Checklist
- [ ] Query uses TYPEOF or Type filter for per-type fields
- [ ] Selective filter (Id, date range) present
- [ ] ELSE branch on TYPEOF handles unmapped types
- [ ] Apex iteration uses `getSObjectType()` or `instanceof` for dispatch
- [ ] Tests seed at least two target-type rows
- [ ] Query plan reviewed for polymorphic selectivity
## Salesforce-Specific Gotchas
1. **Not all polymorphic fields support TYPEOF.** Task, Event, ContentDocumentLink, FeedItem, Note do; verify for newer objects.
2. **`Schema.SObjectType.Task.fields.WhatId.getReferenceTo()`** returns the full list of possible target types at runtime.
3. **TYPEOF cannot be used in subqueries** (inner queries within SELECT list). Plan accordingly.
## Output Artifacts
| Artifact | Description |
|---|---|
| Polymorphic query library | Reusable TYPEOF queries per field |
| Target-type catalog | Field → list of possible objects |
| Dispatcher helper | Apex utility routing by record type |
## Related Skills
- `admin/activity-and-task-patterns` — Activity object model
- `apex/apex-soql-patterns` — SOQL patterns generally
- `data/large-data-volume-patterns` — selectivity and indexing
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!