The documentation states:
Distance is calculated as a straight line—as the crow flies—regardless of geography and topography between the two points.
In reality Salesforce uses the haversine formula to calculate the great-circle distance between two points.
For any two points on a sphere, the haversine of the central angle between them is given by
where
- haversin is the haversine function:
- d is the distance between the two points (along a great circle of the sphere; see spherical distance),
- r is the radius of the sphere,
- : latitude of point 1 and latitude of point 2
- : longitude of point 1 and longitude of point 2
On the left side of the equals sign d/r is the central angle, assuming angles are measured in radians (note that φ and λ can be converted from degrees to radians by multiplying by π/180 as usual).
Solve for d by applying the inverse haversine (if available) or by using the arcsine (inverse sine) function:
where h is haversin(d/r), or more explicitly:
You can confirm this by creating a custom object with two geolocation fields and a formula field which uses the DISTANCE
formula to calculate the distance between the two locations, and then comparing the results to this haversine calculator.
Here are some examples:
Wellington (-41.31666667, 174.81666667) to Salamanca (40.96666667, -5.5)
- Salesforce: 19,968.02154120 km
- Haversine Calculator: 19970 km (to 4 SF)
London (51.507222, -0.1275) to Tokyo (35.689506, 139.6917)
- Salesforce: 9,558.73252169 km
- Haversine Calculator: 9559 km (to 4 SF)
Moscow (55.75, 37.616667) to Nice (43.7034, 7.2663)
- Salesforce: 2,529.41039443 km
- Haversine Calculator: 2529 km (to 4 SF)
Madrid (40.383333, -3.716667) to Sydney (-33.859972, 151.211111)
- Salesforce: 17,686.13743193 km
- Haversine Calculator: 17690 km (to 4 SF)
Pensacola (30.433333, -87.2) to Asmara (15.333333, 38.933333)
- Salesforce: 12,329.08258719 km
- Haversine Calculator: 12330 km (to 4 SF)
A couple of related posts have since appeared in the Salesforce documentation.
How SOQL Calculates and Compares Distances
The DISTANCE function approximates the haversine, or “great circle,” distance calculation within 0.0002%. This formula assumes that the Earth is a perfect sphere, when in fact it’s an ellipsoid: an irregular one. Errors from this assumption can be up to 0.55% crossing the equator, but are usually below 0.3%, depending on latitude and direction of travel.
The DISTANCE function is fine for calculating the 10 stores closest to a customer’s current location. But don’t fuel your plane for a flight from San Francisco to Sydney based on it.
Blog Post: Geolocation Field Types in Salesforce1 Platform
The distance calculation is based on the haversine formula, which is used in mapping and navigation applications and is illustrated below.
You don't need to use a QueryLocator. For example, you could write it like this:
public class MakeRecords implements Database.Batchable<SObject> {
SObject[] queue;
public MakeRecords(SObject[] records) {
queue = records;
}
public static SObject[] start(Database.BatchableContext context) {
return queue;
}
public static void execute(Database.BatchableContext context, SObject[] records) {
insert records;
}
public void finish(Database.BatchableContext context) {
}
}
You could also have some wrapper class and iterate through those items, if that's easier to code. You could even have an array of JSON strings, and deserialize the strings in the execute method.
The only requirement is that your start method must finish in 10 minutes. Normally, this isn't a problem, but do keep in mind that non-QueryLocator implementations will be rather severely limited (5 million or so values instead of 50,000,000 records).
You could even perform the "calculations" you mentioned in the start method, and return the results from start.
Your Visualforce page can periodically poll the AsyncApexJob table by job ID to show the user a progress bar.
Best Answer
There is a separate limit for
Database.getQueryLocator
, and that limit is 50,000,000 rows. It does not matter if you use theString
parameter or the[query]
parameter, you will be subject to 50,000,000 returned rows. The static method is useful when you don't need to alter the fields, objects, sort order, etc, but you want to have full binding capability, while the dynamic method is useful when you want to be able to dynamically assign fields, objects, and so on, at the cost of binding capability.The static method is useful when you'll only ever be querying a specific object with specific fields (which accounts for probably 99% of all use cases), while the dynamic method is useful when you don't know what fields and objects you'll need. For example, I'd imagine that Field Trip (available on the AppExchange) uses this method, because it needs to be able to query any field and any object to determine data population.