---------------------------------------------------------------------------
--
-- PostGIS - Spatial Types for PostgreSQL
-- Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
--
-- This is free software; you can redistribute and/or modify it under
-- the terms of the GNU General Public Licence. See the COPYING file.
--
---------------------------------------------------------------------------

-----------------------------------------------------------------------------
--  GEOGRAPHY TYPE
-----------------------------------------------------------------------------

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_typmod_in(cstring[])
	RETURNS integer
	AS 'MODULE_PATHNAME','geography_typmod_in'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_typmod_out(integer)
	RETURNS cstring
	AS 'MODULE_PATHNAME','postgis_typmod_out'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_in(cstring, oid, integer)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_in'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_out(geography)
	RETURNS cstring
	AS 'MODULE_PATHNAME','geography_out'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION geography_recv(internal, oid, integer)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_recv'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION geography_send(geography)
	RETURNS bytea
	AS 'MODULE_PATHNAME','geography_send'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_analyze(internal)
	RETURNS bool
	AS 'MODULE_PATHNAME','gserialized_analyze_nd'
	LANGUAGE 'c' VOLATILE STRICT;

-- Availability: 1.5.0
CREATE TYPE geography (
	internallength = variable,
	input = geography_in,
	output = geography_out,
	receive = geography_recv,
	send = geography_send,
	typmod_in = geography_typmod_in,
	typmod_out = geography_typmod_out,
	delimiter = ':',
	analyze = geography_analyze,
	storage = main,
	alignment = double
);



-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography(geography, integer, boolean)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_enforce_typmod'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE CAST (geography AS geography) WITH FUNCTION geography(geography, integer, boolean) AS IMPLICIT;

-- Availability: 2.0.0
-- Changed: 2.1.4 ticket #2870 changed to use geography bytea func instead of geometry bytea
CREATE OR REPLACE FUNCTION geography(bytea)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_from_binary'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION bytea(geography)
	RETURNS bytea
	AS 'MODULE_PATHNAME','LWGEOM_to_bytea'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.0.0
CREATE CAST (bytea AS geography) WITH FUNCTION geography(bytea) AS IMPLICIT;
-- Availability: 2.0.0
CREATE CAST (geography AS bytea) WITH FUNCTION bytea(geography) AS IMPLICIT;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_AsText(geography)
	RETURNS TEXT
	AS 'MODULE_PATHNAME','LWGEOM_asText'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 2.5.0
CREATE OR REPLACE FUNCTION ST_AsText(geography, int4)
	RETURNS TEXT
	AS 'MODULE_PATHNAME','LWGEOM_asText'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_AsText(text)
	RETURNS text AS
	$$ SELECT @extschema@.ST_AsText($1::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL
        _COST_MEDIUM;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_GeographyFromText(text)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_from_text'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_GeogFromText(text)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_from_text'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_GeogFromWKB(bytea)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_from_binary'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION postgis_typmod_dims(integer)
	RETURNS integer
	AS 'MODULE_PATHNAME','postgis_typmod_dims'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION postgis_typmod_srid(integer)
	RETURNS integer
	AS 'MODULE_PATHNAME','postgis_typmod_srid'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION postgis_typmod_type(integer)
	RETURNS text
	AS 'MODULE_PATHNAME','postgis_typmod_type'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
-- Changed: 2.4.0 Limit to only list things that are tables
CREATE OR REPLACE VIEW geography_columns AS
	SELECT
		current_database() AS f_table_catalog,
		n.nspname AS f_table_schema,
		c.relname AS f_table_name,
		a.attname AS f_geography_column,
		postgis_typmod_dims(a.atttypmod) AS coord_dimension,
		postgis_typmod_srid(a.atttypmod) AS srid,
		postgis_typmod_type(a.atttypmod) AS type
	FROM
		pg_class c,
		pg_attribute a,
		pg_type t,
		pg_namespace n
	WHERE t.typname = 'geography'
		AND a.attisdropped = false
		AND a.atttypid = t.oid
		AND a.attrelid = c.oid
		AND c.relnamespace = n.oid
		AND c.relkind = ANY (ARRAY['r'::"char", 'v'::"char", 'm'::"char", 'f'::"char", 'p'::"char"] )
		AND NOT pg_is_other_temp_schema(c.relnamespace)
		AND has_table_privilege( c.oid, 'SELECT'::text );

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography(geometry)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_from_geometry'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE CAST (geometry AS geography) WITH FUNCTION geography(geometry) AS IMPLICIT;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geometry(geography)
	RETURNS geometry
	AS 'MODULE_PATHNAME','geometry_from_geography'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE CAST (geography AS geometry) WITH FUNCTION geometry(geography) ;

-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
-- GiST Support Functions
-- ---------- ---------- ---------- ---------- ---------- ---------- ----------

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gist_consistent(internal,geography,int4)
	RETURNS bool
	AS 'MODULE_PATHNAME' ,'gserialized_gist_consistent'
	LANGUAGE 'c';

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gist_compress(internal)
	RETURNS internal
	AS 'MODULE_PATHNAME','gserialized_gist_compress'
	LANGUAGE 'c';

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gist_penalty(internal,internal,internal)
	RETURNS internal
	AS 'MODULE_PATHNAME' ,'gserialized_gist_penalty'
	LANGUAGE 'c';

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gist_picksplit(internal, internal)
	RETURNS internal
	AS 'MODULE_PATHNAME' ,'gserialized_gist_picksplit'
	LANGUAGE 'c';

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gist_union(bytea, internal)
	RETURNS internal
	AS 'MODULE_PATHNAME' ,'gserialized_gist_union'
	LANGUAGE 'c';

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gist_same(box2d, box2d, internal)
	RETURNS internal
	AS 'MODULE_PATHNAME' ,'gserialized_gist_same'
	LANGUAGE 'c';

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gist_decompress(internal)
	RETURNS internal
	AS 'MODULE_PATHNAME' ,'gserialized_gist_decompress'
	LANGUAGE 'c';

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_overlaps(geography, geography)
	RETURNS boolean
	AS 'MODULE_PATHNAME' ,'gserialized_overlaps'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OPERATOR && (
	LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_overlaps,
	COMMUTATOR = '&&',
	RESTRICT = gserialized_gist_sel_nd,
	JOIN = gserialized_gist_joinsel_nd
);

-- Availability: 2.2.0
CREATE OR REPLACE FUNCTION geography_distance_knn(geography, geography)
  RETURNS float8
  AS 'MODULE_PATHNAME','geography_distance_knn'
  LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
  COST 100;

-- Availability: 2.2.0
CREATE OPERATOR <-> (
  LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_distance_knn,
  COMMUTATOR = '<->'
);

-- Availability: 2.2.0
CREATE OR REPLACE FUNCTION geography_gist_distance(internal, geography, int4)
	RETURNS float8
	AS 'MODULE_PATHNAME' ,'gserialized_gist_geog_distance'
	LANGUAGE 'c';


-- Availability: 1.5.0
CREATE OPERATOR CLASS gist_geography_ops
	DEFAULT FOR TYPE geography USING GIST AS
	STORAGE 	gidx,
	OPERATOR        3        &&	,
--	OPERATOR        6        ~=	,
--	OPERATOR        7        ~	,
--	OPERATOR        8        @	,
-- Availability: 2.2.0
	OPERATOR        13       <-> FOR ORDER BY pg_catalog.float_ops,
-- Availability: 2.2.0
	FUNCTION        8        geography_gist_distance (internal, geography, int4),
	FUNCTION        1        geography_gist_consistent (internal, geography, int4),
	FUNCTION        2        geography_gist_union (bytea, internal),
	FUNCTION        3        geography_gist_compress (internal),
	FUNCTION        4        geography_gist_decompress (internal),
	FUNCTION        5        geography_gist_penalty (internal, internal, internal),
	FUNCTION        6        geography_gist_picksplit (internal, internal),
	FUNCTION        7        geography_gist_same (box2d, box2d, internal);

-- moved to separate file cause its invovled
#include "geography_brin.sql.in"

-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
-- B-Tree Functions
-- For sorting and grouping
-- Availability: 1.5.0
-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_lt(geography, geography)
	RETURNS bool
	AS 'MODULE_PATHNAME', 'geography_lt'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_le(geography, geography)
	RETURNS bool
	AS 'MODULE_PATHNAME', 'geography_le'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_gt(geography, geography)
	RETURNS bool
	AS 'MODULE_PATHNAME', 'geography_gt'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_ge(geography, geography)
	RETURNS bool
	AS 'MODULE_PATHNAME', 'geography_ge'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_eq(geography, geography)
	RETURNS bool
	AS 'MODULE_PATHNAME', 'geography_eq'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION geography_cmp(geography, geography)
	RETURNS integer
	AS 'MODULE_PATHNAME', 'geography_cmp'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

--
-- Sorting operators for Btree
--
-- Availability: 1.5.0
CREATE OPERATOR < (
	LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_lt,
	COMMUTATOR = '>', NEGATOR = '>=',
	RESTRICT = contsel, JOIN = contjoinsel
);

-- Availability: 1.5.0
CREATE OPERATOR <= (
	LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_le,
	COMMUTATOR = '>=', NEGATOR = '>',
	RESTRICT = contsel, JOIN = contjoinsel
);

-- Availability: 1.5.0
CREATE OPERATOR = (
	LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_eq,
	COMMUTATOR = '=', -- we might implement a faster negator here
	RESTRICT = contsel, JOIN = contjoinsel
);

-- Availability: 1.5.0
CREATE OPERATOR >= (
	LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_ge,
	COMMUTATOR = '<=', NEGATOR = '<',
	RESTRICT = contsel, JOIN = contjoinsel
);

-- Availability: 1.5.0
CREATE OPERATOR > (
	LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_gt,
	COMMUTATOR = '<', NEGATOR = '<=',
	RESTRICT = contsel, JOIN = contjoinsel
);

-- Availability: 1.5.0
CREATE OPERATOR CLASS btree_geography_ops
	DEFAULT FOR TYPE geography USING btree AS
	OPERATOR	1	< ,
	OPERATOR	2	<= ,
	OPERATOR	3	= ,
	OPERATOR	4	>= ,
	OPERATOR	5	> ,
	FUNCTION	1	geography_cmp (geography, geography);


-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
-- Export Functions
-- Availability: 1.5.0
-- ---------- ---------- ---------- ---------- ---------- ---------- ----------

--
-- SVG OUTPUT
--

-- Changed 2.0.0 to use default args and named args
CREATE OR REPLACE FUNCTION ST_AsSVG(geog geography, rel int4 DEFAULT 0, maxdecimaldigits int4 DEFAULT 15)
	RETURNS text
	AS 'MODULE_PATHNAME','geography_as_svg'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_AsSVG(text)
	RETURNS text AS
	$$ SELECT @extschema@.ST_AsSVG($1::@extschema@.geometry,0,15);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL
        _COST_MEDIUM;

--
-- GML OUTPUT
--

-- ST_AsGML(version, geography, precision, option, prefix, id)
-- Changed: 3.0.0 to bind directly to C
-- Changed: 2.0.0 to use default args and allow named args
-- Changed: 2.1.0 enhance to allow id value
-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_AsGML(version int4, geog geography, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0, nprefix text DEFAULT 'gml', id text DEFAULT '')
	RETURNS text
	AS 'MODULE_PATHNAME','geography_as_gml'
	LANGUAGE 'c' IMMUTABLE  _PARALLEL
	_COST_MEDIUM;

CREATE OR REPLACE FUNCTION ST_AsGML(geog geography, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0, nprefix text DEFAULT 'gml', id text DEFAULT '')
	RETURNS text
	AS 'MODULE_PATHNAME','geography_as_gml'
	LANGUAGE 'c' IMMUTABLE  _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
-- Change 2.0.0 to use base function
CREATE OR REPLACE FUNCTION ST_AsGML(text)
	RETURNS text AS
	$$ SELECT @extschema@._ST_AsGML(2,$1::@extschema@.geometry,15,0, NULL, NULL);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL
        _COST_MEDIUM;

--
-- KML OUTPUT
--

-- AsKML(geography,precision)
-- Changed: 2.0.0 to use default args and named args
CREATE OR REPLACE FUNCTION ST_AsKML(geog geography, maxdecimaldigits int4 DEFAULT 15, nprefix text DEFAULT '')
	RETURNS text
	AS 'MODULE_PATHNAME','geography_as_kml'
	LANGUAGE 'c' IMMUTABLE  _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
-- Deprecated 2.0.0
CREATE OR REPLACE FUNCTION ST_AsKML(text)
	RETURNS text AS
	$$ SELECT @extschema@.ST_AsKML($1::@extschema@.geometry, 15);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL
        _COST_MEDIUM;

--
-- GeoJson Output
--

CREATE OR REPLACE FUNCTION ST_AsGeoJson(geog geography, maxdecimaldigits int4 DEFAULT 9, options int4 DEFAULT 0)
	RETURNS text
	AS 'MODULE_PATHNAME','geography_as_geojson'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
-- Deprecated in 2.0.0
CREATE OR REPLACE FUNCTION ST_AsGeoJson(text)
	RETURNS text AS
	$$ SELECT @extschema@.ST_AsGeoJson($1::@extschema@.geometry, 9, 0);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL
        _COST_MEDIUM;


-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
-- Measurement Functions
-- Availability: 1.5.0
-- ---------- ---------- ---------- ---------- ---------- ---------- ----------

CREATE OR REPLACE FUNCTION ST_Distance(geog1 geography, geog2 geography, use_spheroid boolean DEFAULT true)
	RETURNS float8
	AS 'MODULE_PATHNAME','geography_distance'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Distance(text, text)
	RETURNS float8 AS
	$$ SELECT @extschema@.ST_Distance($1::@extschema@.geometry, $2::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Only expands the bounding box, the actual geometry will remain unchanged, use with care.
-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION _ST_Expand(geography, float8)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_expand'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;


-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
-- Distance/DWithin testing functions for cached operations.
-- For developer/tester use only.
-- ---------- ---------- ---------- ---------- ---------- ---------- ----------

-- Calculate the distance in geographics *without* using the caching code line or tree code
CREATE OR REPLACE FUNCTION _ST_DistanceUnCached(geography, geography, float8, boolean)
	RETURNS float8
	AS 'MODULE_PATHNAME','geography_distance_uncached'
	LANGUAGE 'c' IMMUTABLE STRICT
	_COST_HIGH;

-- Calculate the distance in geographics *without* using the caching code line or tree code
CREATE OR REPLACE FUNCTION _ST_DistanceUnCached(geography, geography, boolean)
	RETURNS float8
	AS 'SELECT @extschema@._ST_DistanceUnCached($1, $2, 0.0, $3)'
	LANGUAGE 'sql' IMMUTABLE STRICT;

-- Calculate the distance in geographics *without* using the caching code line or tree code
CREATE OR REPLACE FUNCTION _ST_DistanceUnCached(geography, geography)
	RETURNS float8
	AS 'SELECT @extschema@._ST_DistanceUnCached($1, $2, 0.0, true)'
	LANGUAGE 'sql' IMMUTABLE STRICT;

-- Calculate the distance in geographics using the circular tree code, but
-- *without* using the caching code line
CREATE OR REPLACE FUNCTION _ST_DistanceTree(geography, geography, float8, boolean)
	RETURNS float8
	AS 'MODULE_PATHNAME','geography_distance_tree'
	LANGUAGE 'c' IMMUTABLE STRICT
	_COST_HIGH;

-- Calculate the distance in geographics using the circular tree code, but
-- *without* using the caching code line
CREATE OR REPLACE FUNCTION _ST_DistanceTree(geography, geography)
	RETURNS float8
	AS 'SELECT @extschema@._ST_DistanceTree($1, $2, 0.0, true)'
	LANGUAGE 'sql' IMMUTABLE STRICT;

-- Calculate the dwithin relation *without* using the caching code line or tree code
CREATE OR REPLACE FUNCTION _ST_DWithinUnCached(geography, geography, float8, boolean)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_dwithin_uncached'
	LANGUAGE 'c' IMMUTABLE STRICT
	_COST_HIGH;

-- Calculate the dwithin relation *without* using the caching code line or tree code
CREATE OR REPLACE FUNCTION _ST_DWithinUnCached(geography, geography, float8)
	RETURNS boolean
	AS 'SELECT $1 OPERATOR(@extschema@.&&) @extschema@._ST_Expand($2,$3) AND $2 OPERATOR(@extschema@.&&) @extschema@._ST_Expand($1,$3) AND @extschema@._ST_DWithinUnCached($1, $2, $3, true)'
	LANGUAGE 'sql' IMMUTABLE;

-- ---------- ---------- ---------- ---------- ---------- ---------- ----------

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_Area(geog geography, use_spheroid boolean DEFAULT true)
	RETURNS float8
	AS 'MODULE_PATHNAME','geography_area'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Area(text)
	RETURNS float8 AS
	$$ SELECT @extschema@.ST_Area($1::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_Length(geog geography, use_spheroid boolean DEFAULT true)
	RETURNS float8
	AS 'MODULE_PATHNAME','geography_length'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Length(text)
	RETURNS float8 AS
	$$ SELECT @extschema@.ST_Length($1::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION ST_Project(geog geography, distance float8, azimuth float8)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_project'
	LANGUAGE 'c' IMMUTABLE _PARALLEL
	_COST_MEDIUM;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION ST_Azimuth(geog1 geography, geog2 geography)
	RETURNS float8
	AS 'MODULE_PATHNAME','geography_azimuth'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION ST_Perimeter(geog geography, use_spheroid boolean DEFAULT true)
	RETURNS float8
	AS 'MODULE_PATHNAME','geography_perimeter'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION _ST_PointOutside(geography)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_point_outside'
	LANGUAGE 'c' IMMUTABLE STRICT
	_COST_DEFAULT;

-- Availability: 2.1.0
CREATE OR REPLACE FUNCTION ST_Segmentize(geog geography, max_segment_length float8)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_segmentize'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION _ST_BestSRID(geography, geography)
	RETURNS integer
	AS 'MODULE_PATHNAME','geography_bestsrid'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION _ST_BestSRID(geography)
	RETURNS integer
	AS 'MODULE_PATHNAME','geography_bestsrid'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_Buffer(geography, float8)
	RETURNS geography
	AS 'SELECT @extschema@.geography(@extschema@.ST_Transform(@extschema@.ST_Buffer(@extschema@.ST_Transform(@extschema@.geometry($1), @extschema@._ST_BestSRID($1)), $2), 4326))'
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.3.x
CREATE OR REPLACE FUNCTION ST_Buffer(geography, float8, integer)
	RETURNS geography
	AS 'SELECT @extschema@.geography(@extschema@.ST_Transform(@extschema@.ST_Buffer(@extschema@.ST_Transform(@extschema@.geometry($1), @extschema@._ST_BestSRID($1)), $2, $3), 4326))'
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.3.x
CREATE OR REPLACE FUNCTION ST_Buffer(geography, float8, text)
	RETURNS geography
	AS 'SELECT @extschema@.geography(@extschema@.ST_Transform(@extschema@.ST_Buffer(@extschema@.ST_Transform(@extschema@.geometry($1), @extschema@._ST_BestSRID($1)), $2, $3), 4326))'
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Buffer(text, float8)
	RETURNS geometry AS
	$$ SELECT @extschema@.ST_Buffer($1::@extschema@.geometry, $2);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.3.x
CREATE OR REPLACE FUNCTION ST_Buffer(text, float8, integer)
	RETURNS geometry AS
	$$ SELECT @extschema@.ST_Buffer($1::@extschema@.geometry, $2, $3);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.3.x
CREATE OR REPLACE FUNCTION ST_Buffer(text, float8, text)
	RETURNS geometry AS
	$$ SELECT @extschema@.ST_Buffer($1::@extschema@.geometry, $2, $3);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_Intersection(geography, geography)
	RETURNS geography
	AS 'SELECT @extschema@.geography(@extschema@.ST_Transform(@extschema@.ST_Intersection(@extschema@.ST_Transform(@extschema@.geometry($1), @extschema@._ST_BestSRID($1, $2)), @extschema@.ST_Transform(@extschema@.geometry($2), @extschema@._ST_BestSRID($1, $2))), 4326))'
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Intersection(text, text)
	RETURNS geometry AS
	$$ SELECT @extschema@.ST_Intersection($1::@extschema@.geometry, $2::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_AsBinary(geography)
	RETURNS bytea
	AS 'MODULE_PATHNAME','LWGEOM_asBinary'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION ST_AsBinary(geography, text)
	RETURNS bytea
	AS 'MODULE_PATHNAME','LWGEOM_asBinary'
	LANGUAGE 'c' IMMUTABLE _PARALLEL
	_COST_LOW;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION ST_AsEWKT(geography)
	RETURNS TEXT
	AS 'MODULE_PATHNAME','LWGEOM_asEWKT'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

CREATE OR REPLACE FUNCTION ST_AsEWKT(geography, int4)
	RETURNS TEXT
	AS 'MODULE_PATHNAME','LWGEOM_asEWKT'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 2.0.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_AsEWKT(text)
	RETURNS text AS
	$$ SELECT @extschema@.ST_AsEWKT($1::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL
        _COST_MEDIUM;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION GeometryType(geography)
	RETURNS text
	AS 'MODULE_PATHNAME', 'LWGEOM_getTYPE'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;

-- Availability: 2.0.0
CREATE OR REPLACE FUNCTION ST_Summary(geography)
	RETURNS text
	AS 'MODULE_PATHNAME', 'LWGEOM_summary'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;

-- Availability: 2.1.0
CREATE OR REPLACE FUNCTION ST_GeoHash(geog geography, maxchars int4 DEFAULT 0)
	RETURNS TEXT
	AS 'MODULE_PATHNAME', 'ST_GeoHash'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;

-- Availability: 2.2.0
CREATE OR REPLACE FUNCTION ST_SRID(geog geography)
	RETURNS int4
	AS 'MODULE_PATHNAME', 'LWGEOM_get_srid'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;

-- Availability: 2.2.0
CREATE OR REPLACE FUNCTION ST_SetSRID(geog geography, srid int4)
	RETURNS geography
	AS 'MODULE_PATHNAME', 'LWGEOM_set_srid'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_LOW;

-- Availability: 2.4.0
CREATE OR REPLACE FUNCTION ST_Centroid(geography, use_spheroid boolean DEFAULT true)
	RETURNS geography
	AS 'MODULE_PATHNAME','geography_centroid'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_MEDIUM;


-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Centroid(text)
	RETURNS geometry AS
	$$ SELECT @extschema@.ST_Centroid($1::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE STRICT _PARALLEL;

-----------------------------------------------------------------------------

-- Only implemented for polygon-over-point
-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION _ST_Covers(geog1 geography, geog2 geography)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_covers'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Stop calculation and return immediately once distance is less than tolerance
-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION _ST_DWithin(geog1 geography, geog2 geography, tolerance float8, use_spheroid boolean DEFAULT true)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_dwithin'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Only implemented for polygon-over-point
-- Availability: 3.0.0
CREATE OR REPLACE FUNCTION _ST_CoveredBy(geog1 geography, geog2 geography)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_coveredby'
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

#if POSTGIS_PGSQL_VERSION >= 120

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_Covers(geog1 geography, geog2 geography)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_covers'
	SUPPORT postgis_index_supportfn
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_DWithin(geog1 geography, geog2 geography, tolerance float8, use_spheroid boolean DEFAULT true)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_dwithin'
	SUPPORT postgis_index_supportfn
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Availability: 3.0.0
CREATE OR REPLACE FUNCTION ST_CoveredBy(geog1 geography, geog2 geography)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_coveredby'
	SUPPORT postgis_index_supportfn
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_Intersects(geog1 geography, geog2 geography)
	RETURNS boolean
	AS 'MODULE_PATHNAME','geography_intersects'
	SUPPORT postgis_index_supportfn
	LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL
	_COST_HIGH;

#else

-- Only implemented for polygon-over-point
-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_Covers(geog1 geography, geog2 geography)
	RETURNS boolean
	AS 'SELECT $1 OPERATOR(@extschema@.&&) $2 AND @extschema@._ST_Covers($1, $2)'
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;

-- Only implemented for polygon-over-point
-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_CoveredBy(geog1 geography, geog2 geography)
	RETURNS boolean
	AS 'SELECT $1 OPERATOR(@extschema@.&&) $2 AND @extschema@._ST_Covers($2, $1)'
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;

-- Availability: 1.5.0
CREATE OR REPLACE FUNCTION ST_DWithin(geog1 geography, geog2 geography, tolerance float8, use_spheroid boolean DEFAULT true)
	RETURNS boolean
	AS 'SELECT $1 OPERATOR(@extschema@.&&) @extschema@._ST_Expand($2,$3) AND $2 OPERATOR(@extschema@.&&) @extschema@._ST_Expand($1,$3) AND @extschema@._ST_DWithin($1, $2, $3, $4)'
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;

CREATE OR REPLACE FUNCTION ST_Intersects(geography, geography)
	RETURNS boolean
	AS 'SELECT $1 OPERATOR(@extschema@.&&) $2 AND @extschema@.ST_Distance($1, $2, false) < 0.00001'
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;

#endif

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Covers(text, text)
	RETURNS boolean AS
	$$ SELECT @extschema@.ST_Covers($1::@extschema@.geometry, $2::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_CoveredBy(text, text)
	RETURNS boolean AS
	$$ SELECT @extschema@.ST_CoveredBy($1::@extschema@.geometry, $2::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;

-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_DWithin(text, text, float8)
	RETURNS boolean AS
	$$ SELECT @extschema@.ST_DWithin($1::@extschema@.geometry, $2::@extschema@.geometry, $3);  $$
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;


-- Availability: 1.5.0 - this is just a hack to prevent unknown from causing ambiguous name because of geography
CREATE OR REPLACE FUNCTION ST_Intersects(text, text)
	RETURNS boolean AS
	$$ SELECT @extschema@.ST_Intersects($1::@extschema@.geometry, $2::@extschema@.geometry);  $$
	LANGUAGE 'sql' IMMUTABLE _PARALLEL;

-----------------------------------------------------------------------------