If you are a Golang developer intending to write a client that interacts with Salesforce, this post is for you. We’ll share how you can annotate your Golang structs to generate SOQL queries to be used in Salesforce APIs and how this will make it easy for you to write Golang clients for Salesforce, without having to hard code those queries.
Querying Salesforce Records via APIs
Salesforce offers REST APIs that allow any third party to integrate with the platform, using their language of choice. One of the API endpoints (
/services/data/<version>/query) allows developers to query Salesforce records using SOQL queries. SOQL is a very powerful SQL-like query language that allows developers to query Salesforce. It has extensive support for a conditional expression to filter the objects being retrieved, as well as very powerful way of performing join operations using relationship queries.
Let’s take a look at an example using the Salesforce object ‘Account’. Below is an incomplete list of fields for the ‘Account’ object. For context, you can find the complete list of fields here.
|AccountNumber||string||Account number assigned to this account|
|AccountSource||picklist||Source of the account record. For example, Advertisement, Data.com, or Trade Show. The source is selected from a picklist of available values|
|BillingAddress||string||Billing address for this account.|
|HasOptedOutOfEmail||boolean||Indicates whether the contact doesn’t want to receive email from Salesforce|
|LastActivityDate||Date||Value is one of the following, whichever is the most recent:
Due date of the most recent event logged against the record.
Due date of the most recently closed task associated with the record.
|NumberOfEmployees||Number||Number of employees working at the company represented by this account|
If you wanted to query all Accounts where AccountSource is one of ‘Advertisement’ or ‘Data.com’ you can write the following SOQL query:
You would then pass the above string as a query parameter to the
/services/data/<version>/query endpoint to fetch the relevant records from Salesforce as follows:
Now let’s look at how we might fetch Salesforce records using Golang.
Using Golang to fetch Salesforce Records
Golang is a statically typed, compiled programming language designed at Google. In recent years it has gained enough popularity to consider it a widely-adopted enterprise language. Want to learn more? Get started with Golang here.
Let’s see how quickly we can call the Salesforce query API using Golang. You start by defining the Golang struct representing the Salesforce object(s) you want to query. Let’s continue using the
Account object described earlier. The Golang struct representation looks as follows (note the JSON annotations to marshal and unmarshal struct to/from JSON):
Then we would model the response from query API as follows:
The following snippet shows one of the ways you can call the Salesforce query API and pass along the required SOQL string:
Note that constructing a SOQL query is quite tedious—especially if you want to add or remove any field from the ‘select’ clause, or add/remove/update filter criteria from the ‘where’ clause. What is especially error prone is that you have to maintain the select clause separately from
Account struct and there is always the danger of things falling out of sync. Additionally, adding a new filter criteria means more code changes with special consideration for different logical operators.
If you were to expose this as a method to be used by different parts of your program, then you will end up taking the SOQL string—or at least the ‘where’ clause—as parameter. That might look something like this:
Notice that you expose yourself to SOQL injection as you are constructing the query by concatenating the string passed to your method. You will need to add enough validations in your method to make sure that doesn’t happen.
You might be asking, isn’t there a simpler way? The answer is: Yes! That’s where new go-soql library comes in.
Introducing go-soql Library
As more and more developers embrace Golang it’s important to provide easier means and ways to interact with Salesforce APIs. One such step is to provide a SOQL annotation library that allows Golang developers to tag their structs similarly to how they tag their structs for JSON marshaling/unmarshaling. And that is the aim of new go-soql library.
This library was developed as an internal project within Salesforce, however we saw value in open sourcing this library for benefit of the Golang developer community. That being said, it’s important to note that this library is not officially supported by Salesforce. It is maintained by the team which heavily relies on this library for its own use cases.
Let’s take a look at how it works. We’ll use the same
Account object and Golang struct defined above, so you can see exactly how this new SOQL tag library makes your life easier. We start by annotating our
Account struct as follows:
If we just want to generate the select clause without conditional expressions then it can be done as follows:
This will result in following string:
Now if you add/remove any field in the
Account struct it will automatically be reflected in the ‘select’ clause. As you might have already noticed this annotation goes hand in hand with
json annotations so the response from the Salesforce API can be directly unmarshalled into the
Account struct (as can be seen from the client code snippet in previous section).
While this addresses one problem in our initial code (addition/removal of new field needs to be maintained in two places), it is, of course, of limited use. We want the full SOQL query to be automatically generated. In order to do so, we need to define a couple more structs:
Now, we can generate a complete SOQL query using the above two structs:
And, voila! This will generate the SOQL query that we expect. Now we can use that in our call to
/services/data/<version>/query API. Note that you can change the
AccountQueryCriteria struct to modify the conditional expression. If you add more than one field to
AccountQueryCriteria then they are combined using the AND logical operator.
Now your client code will look something like this. No more SOQL query string maintenance, or worrying about how to construct where clauses with combinations of different logical operators. Just define your struct and marshal it into SOQL query.
You can also create a function that takes
AccountQueryCriteria as a parameter and exposes it to be used by different parts of your program to query
Account objects using different query criteria.
Since SOQL is generated by using this struct, the SOQL injection vulnerability is addressed. go-soql will take care of constructing a valid SOQL by properly escaping the user provided parameters.
As you can see from above, using the go-soql library for writing Golang clients for Salesforce is much easier since all you need to do is define the struct and annotate it.
Hopefully, you now have an idea of the power of the go-soql library. This blog post just scratches the surface of what the go-soql library can do. The library has extensive support for logical operators as well as child-to-parent and parent-to-child relationships. You can find all those details and more in the README of the repo.
Git repo: https://github.com/forcedotcom/go-soql
Related Trailhead modules:
Atul Kshirsagar is a Software Architect at Salesforce. He is passionate about technology, open source projects and loves to build software. He has presented at multiple conferences and contributed to many open source projects. In his current role as Software Architect at Salesforce he is focussed on leading the efforts to automate the entire patching lifecycle for the DB layer within the Salesforce Platform.