Is it possible to create a calculation field using database abstraction layer?
Yep Haversine should work without a problem. This is slightly modified from a production site which is up and working right now, for example:

$lat = 51.5014;
$lng = 0.1419;

$query = db_select('field_geo_latitude', 'f')
  -&gt;fields('f', array('entity_id'))
  -&gt;orderBy('distance');

$earth_radius = 3959;
$expr = "(
  $earth_radius * acos( 
    cos(radians(:lat))
  * cos(radians(field_geo_latitude))
  * cos(radians(field_geo_longitude) - radians(:lng)) 
  + sin(radians(:lat)) 
  * sin(radians(field_geo_latitude)) 
  )
)";
$query-&gt;addExpression($expr, 'distance', array(':lat' =&gt; $lat, ':lng' =&gt; $long));

$query-&gt;having('distance &lt;= :radius', array(':radius' =&gt; 10));


Resulting query:

SELECT f.entity_id AS entity_id, (
  3959 * acos( 
    cos(radians(:lat))
  * cos(radians(field_geo_latitude))
  * cos(radians(field_geo_longitude) - radians(:lng)) 
  + sin(radians(:lat)) 
  * sin(radians(field_geo_latitude)) 
  )
) AS distance
FROM {field_geo_latitude} f
HAVING  (distance &lt;= :radius) 
ORDER BY distance ASC


When executed all the parameters are replaced as expected.