How do you parse a SOQL AggregateResult column with no value? - salesforce

Let's say you run a SOQL aggregate query that looks like this:
select OwnerId, sum(ExpectedRevenue)val from Opportunity GROUP BY ROLLUP(OwnerId)
For whatever reason, there are no Opportunities with ExpectedRevenue fields populated.
You get a table that looks like this:
val___|OwnerId
|Id1
|Id2
|Id3
4/4 records.
(sidenote: how do you put in tabular data without it looking terrible?)
Take note that the "val" columns are all null and the last OwnerId column is also null.
There are 4 rows because SOQL returns a "total" row as well on rollups.
While looping through the AggregateResult[] that gets returned the code blows up on a line that looks like this: AggregateResult[0].get('val'); with a "System.NullPointerException: Attempt to de-reference a null object"
However, if just 1 of those users has some data, then the whole thing works. So I'm guessing that if no rows have any data in a particular column, that column does not exist at all and calls to retrieve it blow up.
So my question is how do you determine if a column exists to avoid the null reference error?

You have said that the ownerid column and the val columns are all null, therefore AggregateResult[0] is a pointer to a null object and any attempt to get a alue from that object give you the error you are having.
What I expect you want to be doing is before you run
AggregateResult[0].get('val');
you want to have an if statement say
if(AggregateResult.size() > 0)
or possibly
if(AggregateResult[0] != null)
to ensure that you are not attempting to access an empty object.
Try that and it should work. Otherwise post up a bigger code listing to look through.
Paul

If there is no data to summarize for the filters you specify in your where clause you'll get an empty list of AggregateResult back. You can test for this using list isEmpty() in Apex.

Related

System.sobjectexception: sobject row was retrieved via soql without querying the requested field: Asset.Product2

I have a problem on the query on my test class. I have put AssetId__r.Product2Id on the 1st query, and put Product2Id in the Asset query. but still the error persist. as the error says it needs Asset.Product2 which is an SObject , not a field and I am lost on how to fix this error. does anyone encounter this error before? please I need your help.
would be easier if you'd post the actual query.
You probably have something like that in your code:
String name = myObject.AssetId__r.Product2.Name;
but the query SELECT AssetId__r.Product2Id, ... FROM MyTable WHERE ...
So what you can change is put more product fields in the query. You can go up to 5 dots "up".
SELECT AssetId__r.Product2.Id,
AssetId__r.Product2.Name,
AssetId__r.Product2.ProductCode
FROM myObject
WHERE ...
It will work and then Apex that uses it can treat AssetId__r.Product2 as a normal Product2 object, as if it was queried separately. It'll have Id, Name, ProductCode fields set.
The query is also "safe". If AssetId__c is null or Product2Id is null - it'll still execute OK. You'll have to do null checks in Apex (or in query's WHERE clause)

Access a field from another table using the object relation

I am new to SalesForce and SOQL so sorry in advance if the question has already been answered, if yes link it to me.
The aim of my SOQL query is to get all the contract information to generate PDF.
There are tables: Contract, Contact and Account
In the Contract table there are fields: Maitre_d_apprentissage__c, MaitreApprentissageNom1__c, MaitreApprentissagePrenom1__c, Apprenti__c, ApprentiNom__c, ApprentiPrenom__c
There are relationships:
Apprenti__r which link Apprenti__c to Contact table
Maitre_d_apprentissage__r which link Maitre_d_apprentissage__c to Contact table
When I looked at table, I saw that MaitreApprentissageNom1__c was equal to Maitre_d_apprentissage__r.LastName and ApprentiNom__c was equal to Apprenti__r.LastName. So I conclude I could get other information of Apprenti__c and Maitre_d_apprentissage__c from the Contact Table following the same principle. So I added to my query Apprenti__r.Date_de_naissance__c and Maitre_d_apprentissage__r.Date_de_naissance__c to get the Date_de_naissance__c field which is in my Contact table.
I see in the results that the query succeeds in getting the information but some values have changed column (lines 6 and 7), you can see the difference between query 1 and query 2. In the first query I only return the Apprenti__r.Date_de_naissance__c and in the second query I return Apprenti__r.Date_de_naissance__c and Maitre_d_apprentissage__r.Date_de_naissance__c
Query 1:
SELECT ApprentiNom__c, ApprentiPrenom__c, Apprenti__r.Date_de_naissance__c, MaitreApprentissageNom1__c, MaitreApprentissagePrenom1__c
FROM Contract
Result 1:
Query 2:
SELECT ApprentiNom__c, ApprentiPrenom__c, Apprenti__r.Date_de_naissance__c, MaitreApprentissageNom1__c, MaitreApprentissagePrenom1__c, Maitre_d_apprentissage__r.Date_de_naissance__c
FROM Contract
Result 2:
I would like to understand from where is coming the problem and how to correct it. Thank you in advance.
It's possible that it's just your query editor displaying stuff incorrectly. You can see it got confused with 2 lookups to Contact table, why there's even a column header "Contact.Date_de_naissance__c" (and why it's there twice). And they aren't shown in the order you requested...
What editor you're using? You could try built-in "Developer Console" or http://workbench.developerforce.com/
What do you need it for? In Apex order of fields won't matter, in REST API query the values fetched via lookup will come as JSON sub-objects so there will always be a way to figure out exactly which value is coming from which relation.
In Dev Console try to run this and check if it solves your fears:
System.debug(JSON.serializePretty([SELECT
ApprentiNom__c, ApprentiPrenom__c,
Apprenti__r.Date_de_naissance__c,
MaitreApprentissageNom1__c, MaitreApprentissagePrenom1__c,
Maitre_d_apprentissage__r.Date_de_naissance__c
FROM Contract]));
Then add Maitre_d_apprentissage__r.LastName to query and see what changed, what stayed as is.

Query of Arrays in Salesforce

I need to do 1 of two things (I believe):
1- Get a Custom Object ID so I can query it directly
2- Get a list of values of a specific field within the Object entries.
Ultimate End goal:
Add and modify rows in my custom object via external API. However to do this I need to check and make sure my new entry/row does not already exist.
What I have:
I have a custom object (called Customer_Arrays__c). It is a table that I can add new rows to (I will call entrys). Each entry has 6 or 7 fields. 1 of these fields is called (external_ID__c). This is the field I utilize to match to new incoming data to see if the entry already exists, or if it needs to add a new row to my table. This Customer_Arrays__c is a child to my opportunity I believe – it is part of every opportunity and each line item I add has a field defaulted to the opportunity.
Help I need:
1- How do I query the value of my Cutomer_Arrays__c based upon an opportunity ID?
2- How do I query a list of values in my (external_ID__c) based upon an opportunity ID?
Thanks for your help! I have read half a dozen+ posts on similar topics and am missing something. Examples of some Past try's that failed:
Select external_ID__c,FROM Custom_Arrays__c WHERE Opportunity='00...'
Select Id (Select ID, Custom_Arrays__c from Custom_Arrays__c) from Opportunity where id ='00...'
List FROM Custom_Arrays__c WHERE Opportunity='00...'
Select Id, external_ID__c, (Select external_ID__c FROM Custom_Arrays__c) WHERE Opportunity__c='00...'
Thanks again!
Only you know how did you name the lookup field (foreign key) from arrays to Opportunity. You'll need to check in setup, next to where external_ID__c is. Since it's a custom field (gets __c at the end), my guess is you went with default.
Try
SELECT Id, Name, External_Id__c
FROM Customer_Arrays__c
WHERE Opportunity__c = '006...'
Thank you eyescream, that got me almost all the way there. Turns out I also needed a __r for the parent child relationship.
Here is a snip out of my final code that works - I think it covers everything:
SELECT Field1__c, Opportunity__r.Id, Opportunity__r.Opportunity__c,
FROM Customer_Arrays__c
WHERE Opportunity__r.Id = '006...'.
Thank you so very much!!!

How do I select an absent column using a literal using SOQL?

Is it possible to do something like this?
SELECT
Id,
'1999-01-01T23:01:01Z' for Some_New_Date_Field__c,
SystemModstamp
FROM Opportunity
Some_New_Date_Field__c has not been added to Opportunity yet, but I would like to return a literal value for this for now to unblock some downstream engineering work.
It's not possible to include a literal return value for a column in SOQL, and you also cannot set values for arbitrary property names on returned sObjects.
In Aggregate SOQL, but not non-aggregate queries like this one, you can provide a name for a value that's used in the returned List<AggregateResult>; for example, you could do
SELECT OwnerId, MAX(CloseDate) largestCloseDate FROM Opportunity GROUP BY OwnerId
and get back AggregateResult objects that have a property largestCloseDate. I don't think that helps you here.

Salesforce SOQL REST Query with empty fields

If I make an SOQL query such as:
select Id, Username, UserRoleId from User
The API correctly returns the results as XML, however because none of the rows contain a UserRoleId entry this node is completely excluded from the results.
Ideally I would like to be able to create a table from the resultant XML showing all the requested columns, even if they are empty. Is there a way of forcing the API to return even empty columns so that I can do this without resorting to something messy like parsing the SOQL query?
Isn't it a better idea to when you receive an result. Check if the curtain column row is empty. When the column is empty, than you know you have set a empty column by yourself. It is just an idea of my.
Think about a try catch, just an example I use in my application:
try {
parentId = records.getJSONObject(i).getJSONObject("Parent).getString("Name");
catch (JSONException e) {
parentId = "a";
}
When the column name from Parent is empty, then parentId = a. I'd set it manually because I know some other data rolls could have that data.

Resources