0

On my managed package, I have a custom field: namespace__A__c The user also has a custom field A__c

If I do the following SOQL (dynamic or not)

SELECT Id, Name FROM Contact WHERE A__c != NULL

it always appends the package namespace, and I cannot query the user's custom object.

How can I force an SOQL inside my managed package to not query the namespaced custom field? How to do that in Apex directly?

NOTES:

  • there's a comment here from @daniel-ballinger saying that isn't possiblem but it's 4 years old, maybe there's a new trick.
  • To do a DML operation, we can pass the Object schema, and it works.
5
  • The only apex-based workaround (i.e. avoiding using REST API) I'm aware of is to ensure that the SOQL query is executed in a class that is not part of the managed package. The package calls the unpackaged code (e.g. via Callable API) and receives back the results...
    – Phil W
    Feb 5 at 17:04
  • Depending on the field type,. the quick and dirty way is to create a formula field that points at the customer's field, and just query for that Feb 5 at 22:46
  • @BritishBoyinDC Wouldn't that have the same issue?
    – fred
    Feb 5 at 23:23
  • 2
    The issue is only if the field name is identical to one in the package -so if you create a formula field with a different api name, you don't get the collision Feb 5 at 23:47
  • 1
    @BritishBoyinDC Actually, this is what I suggested to our client, and it worked. Not a pretty solution but at least he could run a SQOL with his custom field. Feb 7 at 10:39

1 Answer 1

0

You could retrieve both A__c and NS__A__c fields calling Query REST API.
Keep in mind that to execute a SOQL via API you must always add the namespace to every field/object included in your managed package, so if in apex you have something like

SELECT Name, MyField__c FROM MyObject__c LIMIT 3

you should change it to

SELECT+Name,NS__MyField__c+FROM+NS__MyObject__c+LIMIT+3

The result will be a JSON like this:

{
  "totalSize" : 3,
  "done" : true,
  "records" : [ {
    "attributes" : {
      "type" : "NS__MyObject__c",
      "url" : "/services/data/v58.0/sobjects/NS__MyObject__c/a0j8d000009DJ5YAAW"
    },
    "NS__MyField__c" : "0001",
    "Name" : "aaaa"
  }, {
    "attributes" : {
      "type" : "NS__MyObject__c",
      "url" : "/services/data/v58.0/sobjects/NS__MyObject__c/a0j8d000009DJ5OAAW"
    },
    "NS__MyField__c" : "0002",
    "Name" : "bbbb"
  }, {
    "attributes" : {
      "type" : "NS__MyObject__c",
      "url" : "/services/data/v58.0/sobjects/NS__MyObject__c/a0j8d000009DJ5AAAW"
    },
    "NS__MyField__c" : "0003",
    "Name" : "cccc"
  } ]
}

You could deserialize the records property into a list of SObject, i.e.:

List<MyObject__c> aList = (List<MyObject__c>) JSON.deserialize(result.records, List<MyObject__c>.class);

If you need more than 2000 records it may not be worth it, since you have to execute multiple API calls.

Please also note that a security review may fail if you use UserInfo.getSessionId(), you could read more about it here.

3
  • In 2023, there was definitely a change in the security review policies and using the REST API will fail the security review. Feb 5 at 22:41
  • @SamuelCarreira The security review will fail only if you use UserInfo.getSessionId(). Using REST/Tooling/Metadata API is fine, I added a link in the answer, several users of SFSE passed the security review and added their solutions to that post
    – RubenDG
    Feb 6 at 8:40
  • When I had to implement a system to access the tooling API I ended up creating an open-source package so the client could install it without issues. It uses the trick to get UserSessionId from the VisualForce page context. Because the "connected app methods" aren't the best experience for an AppExchange easy to use app. Feb 7 at 10:44

You must log in to answer this question.

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