0

EDIT: I am using simple-salesforce with the REST API to make requests.

I'm trying to get for each Case all the EmailMessages, and for each EmailMessage, all its ContentDocumentLinks (from which I can get the ContentDocument).

This query fails with "Malformed Query":

SELECT
    Id,
    (
    SELECT
        Id,
        (
        SELECT
            Id
        FROM
            ContentDocumentLinks
        )
    FROM
        EmailMessages
    )
FROM
    Case
LIMIT 1

However these two queries work perfectly:

SELECT
    Id,
    (
    SELECT
        Id
    FROM
        ContentDocumentLinks
    )
FROM
    EmailMessage
LIMIT 1
SELECT
    Id,
    (
    SELECT
        Id
    FROM
        EmailMessages
    )
FROM
    Case
LIMIT 1

What did I miss? Is there a way to achieve what I wanted?

1 Answer 1

4

edit:

So the question ended up being about simple salesforce (python) and thus running this query through the REST API.

Having multiple levels of subqueries was introduced in Summer '23 (api v58.0), and can be taken advantage of if you're performing the query through the REST API.

You just need to make sure to specify an API version of at least 58 when using simple salesforce to login.

e.g.

sf = Salesforce(
    username='[email protected]', 
    password='password', 
    security_token='token', 
    version='58.0')

or

session_id, instance = SalesforceLogin(
    username='[email protected]',
    password='password',
    security_token='token',
    sf_version='58.0')

Alternatively, keeping simple-salesforce up to date with pip install simple-salesforce --upgrade should do the trick. The DEFAULT_API_VERSION constant is updated every so often, and has been set to 59.0 since v1.12.6 (2024-02-26). The latest version on pypi is currently 1.12.5 though.

Original answer:

In Apex, we're only allowed to query down one level of an object hierarchy. I.e. you can't have a subquery in a subquery like you've tried to do.

You either need to break it up into two separate queries, or change the FROM object to be on EmailMessage.

If you already have the Case Id, then it'd be something like

SELECT
    /* While we can only query down one level, we can query "up" */
    /* the hierarchy (from child -> parent) up to 5 levels */
    /* E.g. Parent.Account.Parent.Owner.Manager.Name */
    Parent.Id,
    Id, TextBody, To,
    (SELECT Id FROM ContentDocumentLinks)
FROM
    EmailMessage
WHERE
    ParentId = :myCaseId
6
  • Thank you for your help! Are you sure? On developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/… there is a query with "five levels of parent-child relationships". Also, I'm not using apex, just SOQL with the REST API.
    – Labo
    Commented Mar 7 at 12:02
  • 3
    You had not made it known that you were using the REST API. That combined with the error, and the natural assumption was that you were using Apex where that isn't allowed. Editing your question to show the URL that you're constructing would probably be helpful. Could be as simple as you needing to use a more recent API version in your REST call (querying down multiple levels was introduced fairly recently, looks like in v58.0).
    – Derek F
    Commented Mar 7 at 12:07
  • Thank you a lot! All I needed was to add a version="59.0" parameter to my call to Salesforce. Feel free to write an answer, I'll gladly accept it!
    – Labo
    Commented Mar 8 at 8:17
  • 1
    @Labo Updated my answer.
    – Derek F
    Commented Mar 8 at 13:16
  • thank you! Note: my simple-salesforce was up to date with DEFAULT_API_VERSION=59.0. I think the API relied on some server-side configuration.
    – Labo
    Commented Mar 8 at 13:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .