GEOGRAPHY are different PostgreSQL
TYPES; exposed as higher level (SQL), user-defined composite types to the psql environment, but implemented as lower level (C) base types.
These base types are defined on the C level with e.g. their own typemod constraints, TOAST support, data I/O functions, operator classes and casting behaviour. On top of that, both types have their own indexing mechanics.
On the SQL level, both types (optionally) accept a
TEXT and a
NUMERIC parameter, which translate to geometry type, and spatial reference. Additionally, you can index both with the same command (
USING GIST(<geom>)), although internally those indexes differ, and
CAST between them almost seamlessly, with some caveats as seen in the example below.
- In every way, these are different types with fundamentally different mechanics, despite their deliberately similar handling.
Under the hood, the core difference is the mathematical representation and calculation of and with the given coordinates, in two words: planar vs. spheroidal.
GEOMETRY type is bound by definition to a 2D planar reference, and operates with Cartesian math regardless of the nature of the CRS; distance between two points is a straight line as e.g. per Pythagoras, even if your geometries are defined in a geodetic reference (e.g. EPSG:4326). The
GEOMETRY type is meant to work best for projected CRS.
GEOGRAPHY type is inherently assuming that the given coordinates are geodetic coordinates, thus operating solely on great circle math (spherical) and/or it's more complicated application on spheroidal/ellipsoidal bodies. The
GEOGRAPHY type is meant to work with geographic/geodetic RS (Longitudes/Latitudes) only.
- Neither does PostGIS "the same 'Geography calculations'", nor detects the nature of a given SRS to do so.
The WGS84 ellipsoid (EPSG:7030) is allegedly among the most usable representation of our planet on a global scale, and is widely supported in transformations to and from projections and other ellipsoids. Also, it is and has ever since been the base reference of most of our positioning systems.
It is de facto a global standard for spatial data storage and its interchangeability.
- In PostGIS, the actual default SRS is no SRS, or
0 (which is bad to have...).
Now, as a small example of what PostGIS does with wrong SRS definitions; you can do this (note that the coordinates should represent degrees...)
SELECT ST_AsText(ST_SetSRID('POINT(1000 1000)'::GEOMETRY, 4326));
returning a valid
SELECT ST_AsText(ST_SetSRID('POINT(1000 1000)'::GEOGRAPHY, 4326));
returns a valid
along with the note
Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY
Btw. coercing here means sth. like
-90 + (1000 % 90) = -80
-180 + (1000 % 180) = -80
so it effectively walks around the globe until 1000 degrees are traversed.
GEOGRAPHY type does not care if you do
SELECT ST_AsText(ST_SetSRID('POINT(1000 1000)'::GEOGRAPHY, 3857));
except for the above note of coordinate range coercion, while it actually should (if it could; we're assigning a SRS on the created type, so it would be the function assigning it that needed to) inform you about the nature of the SRS (and, since we're at it, IMHO also the uselessness of EPSG:3857...).
GEOGRAPHY will indeed check the SRS and denies the cast for non-geodetic SRS, e.g.
SELECT ST_SetSRID('POINT(0 0)'::GEOMETRY, 3857)::GEOGRAPHY;
will error out with
ERROR: Only lon/lat coordinate systems are supported in geography.
- In no way does PostGIS any fail-saving for you in these matters, except when using a
Update as per comment request:
Because PostGIS defines the cast from
GEOGRAPHY (and only this way)
AS IMPLICIT, PostgreSQL is free to cast any
GEOGRAPHY whenever it is necessary, or possible, to solve ambuiguity. This affects parameters to functions in the following ways, where PostgreSQL will
if a distinct signature is unambiguously invoked that accepts only
GEOGRAPHY types; an example would be the
ST_Area signatures where, when explicitly used with a value for
use_spheroid, PG casts a
an ambiguous signature for both types is used (i.e. a type overloaded function), and only one parameter is passed in as
GEOGRAPHY, the other will get cast; an example is
ST_DWithin where, when one parameter gets passed as
GEOMETRY and the other as
GEOGRAPHY, the former will get cast to
One might say, since only the
IMPLICIT, it has inherent precedence.
In these cases, since the
CAST is used, PostGIS will inform you (and deny the execution) if the
GEOMETRY in question does not use a geodetic SRS!
- The secret ingredient to ambiguity is an implicit