Chapter 7. Differences

1. Differences between JASPA and PostGIS
1.1. Box Data Type
1.2. Coordinate dimensions
1.3. Empty Geometries
1.4. Dump functions
2. Differences between JASPA for PostgreSQL and for H2
2.1. Letter Case
2.2. Casts
2.3. Arrays
2.4. Aggregates
2.5. Renamed Functions

1. Differences between JASPA and PostGIS

For the users acquainted with PostGIS, in the following sections the differences between JASPA and PostGIS are exposed.

1.1. Box Data Type

PostGIS has a set of box data types to manage the bounding box of a geometry. The set of box types includes the box2d, box3d and box3d_extent types. A box is composed of x_min, y_min, x_max and y_max coordinates. Those data types aren't OGC valid and they don't exist in JASPA. JASPA uses a standard geometry data type instead of using box types.

1.1.1. PostGIS Box Functions

In the table below, you can find the functions that use Box types in PostGIS and how JASPA handles them.

JASPAPostGISDescription
geometry ST_Box2D (Geometry);box2d Box2D (geometry);Returns a Polygon geometry representation of the two-dimensional bounding box.
geometry ST_Box3D (Geometry);box3d Box3D (geometry);Returns a Polygon geometry representation of the three-dimensional bounding box
geometry ST_Expand (Geometry, Expand_Units);

geometry ST_Expand (geometry, Expand_Units);

box2d ST_Expand (box2d, units_to_expand);

box3d ST_Expand (box3d, units_to_expand);

Expands the Polygon that represents the Bounding Box in all directions.
geometry ST_Extent (Geometry_Aggregate);box3d ST_Extent (geometry_set);Returns the minimum bounding box of the specified geometries, that is, a single rectangle that minimally encloses the geometries.
geometry ST_Extent3D(Geometry_Aggregate);box3d ST_Extent3D (geometry set);Returns the minimum bounding box of the specified geometries.
geometry ST_MakeBox2D (point, point);box2d ST_MakeBox2D (pointLowLeft, pointUpRight);Creates a Box2d defined by the lower left point and the upper right point.
geometry ST_MakeBox3D (point, point);box3d ST_MakeBox3D (pointLowLeft, pointUpRight);Creates a Box3d defined by the lower left point and the upper right point.
double ST_XMax (Geometry);float ST_XMax (box3d);Returns the maximum X of the geometry bounding box.
double ST_XMin (Geometry);float ST_XMin (box3d);Returns the minimum X of the geometry bounding box.
double ST_YMax (Geometry);float ST_YMax (box3d);Returns the maximum Y of the geometry bounding box.
double ST_YMin (Geometry);float ST_YMin (box3d);Returns the minimum Y of the geometry bounding box.
double ST_ZMax (Geometry);float ST_ZMax (box3d);Returns the maximum Z of the geometry bounding box.
double ST_ZMin (Geometry);float ST_ZMin (box3d);Returns the minimum Z of the geometry bounding box.

1.1.2. Automatic Cast of PostGIS Box types

JASPA is able to read Boxes types but automatically converts them to geometry types.

SELECT ST_AsText(ST_GeomFromText('BOX(0 0,10 10)'));
                st_astext
-----------------------------------------
 POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
(1 row)

SELECT ST_AsText(ST_GeomFromText('BOX3D(0 0 -5,10 10 5)'));
                      st_astext
------------------------------------------------------
 POLYGON ((0 0 -5, 0 10 5, 10 10 5, 10 0 -5, 0 0 -5))
(1 row)

SELECT ST_Area(ST_GeomFromText('BOX(0 0,10 10)'));
 st_area
---------
     100
(1 row)

1.1.3. Examples

The following example shows the different behaviour of JASPA and PostGIS when dealing with Boxes.

  • JASPA for PostgreSQL
    SELECT ST_AsEWKT(ST_MakeBox2D(ST_PointFromText('POINT(0 0)'),ST_PointFromText('POINT(10 10)')));
    --Result:
    POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
    
    SELECT ST_MakeBox3D(ST_PointFromText('POINT(0 0 10 2)'),ST_PointFromText('POINT(10 10
    10 4)')) As BB;
                       bb                         
    ----------------------------------------------------
     \001\003\000\000\ ... 00\000\000\000\000\000\000\000
    (1 row)
  • JASPA for H2
    SELECT ST_AsEWKT(ST_MakeBox2D(ST_PointFromText('POINT(0 0)'),ST_PointFromText('POINT(10 10)')));
    --Result:
    POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))    
    
    SELECT ST_MakeBox3D(ST_PointFromText('POINT(0 0 10 2)'),ST_PointFromText('POINT(10 10
    10 4)')) As BB;
    --Result:
    BB  
    0103000080 ... 000000 
  • PostGIS
    SELECT ST_AsEWKT(ST_MakeBox2D(ST_GeomFromEWKT('POINT(0 0)'),ST_GeomFromEWKT('POINT(10 10)')));
    --Result:
                 st_asewkt
    ------------------------------------
     POLYGON((0 0,0 10,10 10,10 0,0 0))
    (1 row)
    
    
    SELECT ST_MakeBox3D(ST_GeomFromEWKT('POINT(0 0 10 2)'),ST_GeomFromEWKT('POINT(10 10 10 4)')) As BB;
               bb
    ------------------------
     BOX3D(0 0 10,10 10 10)
    (1 row)

1.2. Coordinate dimensions

The OGC specifications SFS 1.0 (1999) and SFS 1.1.0 (2005) were 2D with no support for Z coordinate.

The OGC 1.2.0 SFS specification, appeared in 2006, develops the previous specifications to support Z and M (measure) coordinates. ISO SQL-MM Part 3 also supports Z and M Coordinates.

1.2.1. Coordinate Space

We can find four coordinate spaces:

  • XY: each point or vertex is identified by two coordinates (X,Y)

  • XYZ: each point or vertex is identified by three coordinates (X,Y,Z)

  • XYM: each point or vertex is identified by two coordinates and stores a Measure as well (X,Y,M)

  • XYZM: each point or vertex is identified by three coordinates and stores a Measure as well (X,Y,Z,M)

JASPA doesn't support XYM geometries, it automatically converts XYM geometries to XYZM setting Z coordinate to 0.

Coordinate SpaceExampleResult JASPAResult PostGIS
XY
SELECT ST_AsEWKT(
 ST_GeomFromEWKT('POINT(1 2)')) as ga;
POINT (1 2)
POINT(1 2)
XYZ
SELECT ST_AsEWKT(
 ST_GeomFromEWKT('POINT(1 2 3)')) as ga;
POINT(1 2 3)
POINT(1 2 3)
XYM
SELECT ST_AsEWKT(
 ST_GeomFromEWKT('POINTM(1 2 4)')) as ga;
POINT (1 2 0 4)
POINTM(1 2 4)
XYZM
SELECT ST_AsEWKT(
 ST_GeomFromEWKT('POINT(1 2 3 4)')) as ga;
POINT (1 2 3 4)
POINT(1 2 3 4)

1.2.2. Geometry Outputs

PostGIS define ST_AsText() and ST_AsBinary() functions that only output 2D geometries, as stated in OGC SFS 1.0. Unlike PostGIS, JASPA define these functions to support Z and M coordinates.

FunctionJASPAPostGIS
ST_AsBinary4D2D
ST_AsText4D2D
ST_AsEWKB4D + SRID4D + SRID
ST_AsEWKT4D + SRID4D + SRID
JASPA
SELECT ST_AsEWKT(ST_GeomFromText('LINESTRING(-3.52 41.0 20,2.33 48.86 30)',4326)) as ga;
--Result
                        ga
---------------------------------------------------
 SRID=4326;LINESTRING (-3.52 41 20, 2.33 48.86 30)
(1 row)


SELECT ST_AsText(ST_GeomFromText('LINESTRING(-3.52 41.0 20,2.33 48.86 30)',4326)) as ga;
--Result
                   ga
-----------------------------------------
 LINESTRING (-3.52 41 20, 2.33 48.86 30)
(1 row)
PostGIS
SELECT ST_AsEWKT(ST_GeomFromText('LINESTRING(-3.52 41.0 20,2.33 48.86 30)',4326)) as ga;
--Result
WARNING:  OGC WKT expected, EWKT provided - use GeomFromEWKT() for this
                       ga
-------------------------------------------------
 SRID=4326;LINESTRING(-3.52 41 20,2.33 48.86 30)
(1 row)

SELECT ST_AsText(ST_GeomFromText('LINESTRING(-3.52 41.0 20,2.33 48.86 30)',4326)) as ga;
--Result
WARNING:  OGC WKT expected, EWKT provided - use GeomFromEWKT() for this
               ga
---------------------------------
 LINESTRING(-3.52 41,2.33 48.86)
(1 row)

1.2.3. Mixed Dimension Geometries

JASPA can handle with mix dimensionality in a geometry. JASPA would associate the coordinate dimension of the first point to the entire geometry. For it, JASPA will drop the unnecessary coordinates or will add zeros to the unknown coordinates.

[Note]

Keep in mind that every vertex in a geometry should have the same dimensionality. This is just a solution for an undesirable mistake.

1st Point Coordinate SpaceExampleResult JASPA
XY
SELECT ST_Asewkt( ST_GeomFromText('
 GEOMETRYCOLLECTION(
  POINT (5 5),
  LINESTRING (0 0 5, 0 50))'));
GEOMETRYCOLLECTION (POINT (5 5), 
  LINESTRING (0 0, 0 50)
XYZ
SELECT ST_Asewkt(ST_GeomFromText('
 GEOMETRYCOLLECTION(
  POINT (5 5 10),
  LINESTRING (0 0, 0 50))'));
GEOMETRYCOLLECTION (POINT (5 5 10), 
  LINESTRING (0 0 0, 0 50 0))
XYZM
SELECT ST_Asewkt(ST_GeomFromText('
 GEOMETRYCOLLECTION(
   POINT (5 5 10 8),
   LINESTRING (0 0 2, 0 50))'));
GEOMETRYCOLLECTION (POINT (5 5 10 8), 
LINESTRING (0 0 2 0, 0 50 0 0))
PostGIS
SELECT ST_Asewkt( ST_GeomFromText('
 GEOMETRYCOLLECTION(  POINT (5 5), LINESTRING (0 0 5, 0 50))'));

--Result
ERROR:  can not mix dimensionality in a geometry

1.3. Empty Geometries

A geometry is empty if it does not have any points. "POINT EMPTY" or "LINESTRING EMPTY" are examples of empty geometries. JASPA and PostGIS address empty geometries in different ways. While JASPA converts to NULL every empty geometry, PostGIS returns GEOMETRYCOLLECTION EMPTY, regardless of the actual type of input EMPTY geometry.

SELECT ST_AsText(ST_GeomFromText('POINT EMPTY'));

--Result JASPA:
null

--Result PostGIS:
GEOMETRYCOLLECTION EMPTY

Functions

In JASPA, if the input geometry is an empty set, any function will always return as result the null value.

SELECT ST_Envelope(ST_GeomFromText('POINT EMPTY'));
--Result JASPA:
null

--Result PostGIS:
    st_envelope
--------------------
 010700000000000000
(1 row)

Spatial Intersection

Geometries that do not intersect, will return as their intersection an empty geometry. Consequently, as stated before, the result of disjoint intersections will be different in JASPA and PostGIS.

SELECT ST_astext(ST_Intersection (
ST_GeomFromText('POLYGON ((1 3, 1 8, 6 8, 6 3, 1 3))') ,
ST_GeomFromText('POLYGON((8 8, 6 10, 8 10, 8 8))')));

--Result JASPA:
null

--Result PostGIS:
GEOMETRYCOLLECTION EMPTY

1.4. Dump functions

Dump functions include ST_Dump, ST_DumpPoints, ST_DumpRings

Whereas JASPA Dump functions return just an array of geometries, PostGIS Dump functions create an array of geometries with an array of integers (path). The following table shows the different behaviour:

Database1st Example2nd Example
JASPA for PostgreSQL
SELECT st_dump(st_geomfromtext(
 'MULTIPOINT (1 2, 3 4, 5 6)'
 ));

--Result:
         st_dump
---------------------------
 \001\001\ ... 000\000\000@
 \001\001\ ... 000\000\020@
 \001\001\ ... 000\000\030@
SELECT ST_AsText(ST_Dump 
 (ST_GeomFromText('MULTIPOINT (1 2, 3 4, 5 6)'))
 );

or

SELECT ST_AsText(geom) FROM 
 ST_Dump(ST_GeomFromText(' MULTIPOINT (1 2, 3 4, 5 6)')) 
 as geom;

--Result:

  st_Astext
-------------
POINT (1 2)
POINT (3 4)
POINT (5 6)
JASPA for H2
SELECT geom from 
 st_dump ('select st_geomfromewkt('
  'MULTIPOINT (1 2, 3 4, 5 6)'
 ')as geom');

--Result:
GEOM   
01010000 ... 00000000000040 
01010000 ... 00000000001040 
01010000 ... 00000000001840
SELECT ST_AsText(geom) from st_dump ('select 
 st_geomfromewkt('' MULTIPOINT (1 2, 3 4, 5 6)'') as geom'
 );

--Result:
JASPA.ST_ASTEXT(GEOM)   
POINT (1 2) 
POINT (3 4) 
POINT (5 6) 
PostGIS
SELECT ST_Dump (ST_GeomFromText
 ('MULTIPOINT (1 2, 3 4, 5 6)')
 );

--Result:
           ST_Dump
------------------------------
({1},01010000 ... 00000000040)
({2},01010000 ... 00000001040)
({3},01010000 ... 00000001840)
SELECT ST_AsText(a.geom) FROM (SELECT 
 (ST_Dump(ST_GeomFromEWKT(' MULTIPOINT (1 2, 3 4, 5 6) '))).geom 
  AS geom) AS a;

or 

SELECT ST_AsText( 
 (ST_Dump(ST_GeomFromText(' MULTIPOINT (1 2, 3 4, 5 6)' ))).geom
 );

--Result:

  st_Astext
-------------
POINT (1 2)
POINT (3 4)
POINT (5 6)

2. Differences between JASPA for PostgreSQL and for H2

2.1. Letter Case

H2 database converts to uppercase the names of tables or field unless you enclose them in double quotation marks. By contrary, PostgreSQL database converts to lower case every unquotated letter.

For instance, the following SQL sentence would create in PostgreSQL a table test(id), while in H2 the table is named TEST(ID).

create table test (id serial PRIMARY KEY);

This must be considered when you pass table and column names as parameters. The following example shows the different use of the function AddGeometryColumn in PostgreSQL and H2.

--PostgreSQL
SELECT AddGeometryColumn ('','public','test','geom_point',4326,'POINT',2);

--H2
SELECT AddGeometryColumn ('PUBLIC','TEST','GEOM_POLYGON',25830,'MULTIPOLYGON',4);

Alternatively, this issue could be easily solved using double quotation marks. The result of the following SQL sentence is the same in both databases, the table is named test(id).

create table "test" ("id" serial PRIMARY KEY);

2.2. Casts

Casts are used to convert from one data type to another. In PostgreSQL database, it is allowed to define casts in user-defined types like geometries. By contrast, in H2, those casts are not allowed. So, only JASPA for PostgreSQL have defined casts to convert geometry data to others data types.

Anyway, it is advisable to avoid using casts and instead use OGC functions to transform from one data type to another. The main reason, as we've already stated, is that casts are not well supported in all databases.

This section, explains the casting behaviour for JASPA in PostgreSQL.

2.2.1. Explicit Casts

A cast can be invoked in two different ways, CAST(x AS typename) or x::typename.

JASPA for PostgreSQL
PostgreSQL
SELECT ST_Length('LINESTRING (1 2,3 5)'::geometry);
SELECT ST_Length(CAST('LINESTRING (1 2,3 5)' AS geometry));

--Result
    st_length
------------------
 3.60555127546399
(1 row)

2.2.2. Implicit Casts

A cast can be done automatically in which case, you do not invoke it by CAST(x AS typename) or x::typename. This is useful when you give an input parameter to a function that only works with other parameter type and there is an automatic cast.

Once again, it is wiser to use OGC conversion functions to prevent surprising interpretations and for compatibility with others databases.

There are two implicit casts defined for the Geometry type:

  1. Text => Geometry

    SELECT ST_AsText(ST_MakeBox2D('POINT(0 0)','POINT(10 10)'));
    
                    st_astext
    -----------------------------------------
     POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
    (1 row)

    Standard Conversion with OGC function

    SELECT ST_AsText(ST_MakeBox2D(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('POINT(10 10)')));
  2. Bytea => Geometry

    SELECT ST_LineFromWKB(ST_AsBinary('LINESTRING (0 0, 4 5,10 10)'));
    
           st_linefromwkb
    ------------------------------------
     \001\002\000\000\ ... \000\000$@
    (1 row)

    Standard Conversion with OGC function

    SELECT ST_LineFromWKB(ST_GeomFromText('LINESTRING (0 0, 4 5,10 10)'));

2.3. Arrays

An array data type is called by appending square brackets ( [ ] ) to the data type name of the array elements. The functions that support geometry arrays indicate it in their definition. For instance ST_MakeLine includes:

geometry ST_MakeLine(bytea[] point array);

The way to create an array is completely different in PostgreSQL and H2. The following example shows how to construct an array for each database.

PostgreSQL

--(1st Version)--
SELECT asewkt(ST_MakeLine(Array[ST_MakePoint(0, 0), ST_MakePoint(10, 10),ST_MakePoint(15, 10)]));

--Result
             asewkt
--------------------------------
 LINESTRING (0 0, 10 10, 15 10)
(1 row)

--(2nd Version)--
SELECT ST_AsText(ST_Makeline(ST_Accum(geom))) as myline
FROM
(SELECT ST_GeomFromText('SRID=10;POINT(0 0)') as geom
union
SELECT ST_GeomFromText('SRID=10;POINT(10 10)') 
union 
SELECT ST_GeomFromText('SRID=10;POINT(15 15)') 
) as geom;

--Result
          myline
------------------------------
LINESTRING (15 15, 0 0, 10 10)

H2

To construct an array we make use of the function ST_Accum which constructs an array of geometries from a set of geometries.

--(1st Version)--
SELECT ST_AsText(ST_Makeline(st_accumagg(geom))) as myline from (select array_get(
(
st_geomfromtext('POINT(0 0)'),
st_geomfromtext('POINT(10 10)'),
st_geomfromtext('POINT(15 15)')
),x)::binary as geom from (select x from system_range(1,3) as foo) as tabla);

--Result
MYLINE  
LINESTRING (0 0, 10 10, 15 15)

--(2nd Version)--
SELECT ST_AsText(ST_Makeline(ST_Accumagg(geom))) as myline
FROM
(SELECT ST_GeomFromText('SRID=10;POINT(0 0)') as geom
union
SELECT ST_GeomFromText('SRID=10;POINT(10 10)') 
union 
SELECT ST_GeomFromText('SRID=10;POINT(15 15)') 
) as geom;

--Result
MYLINE  
LINESTRING (15 15, 0 0, 10 10)

2.4. Aggregates

Every aggregate function has been renamed in JASPA for H2 database by adding an "Agg" suffix. In the following table the spatial aggregate functions are listed.

PostgreSQLH2Description
ST_AccumST_AccumAggConstructs an array of geometries from a set of geometries.
ST_CollectST_CollectAggReturns a geometry from the collection of others geometries.
ST_ExtentST_ExtentAggReturns the minimum bounding box of the specified geometries, that is, a single rectangle that minimally encloses the geometries.
ST_Extent3DST_Extent3DAggReturns the minimum bounding box of the specified geometries.
ST_LastST_LastAggReturns the last geometry of a set of geometries.
ST_MakeGeomCollST_MakeGeomCollAggConstructs a GeometryCollection object from a set of Geometries.
ST_MakeLineST_MakeLineAggCreates a LineString from a number of points.
ST_MemUnionST_MemUnionAggSame as ST_Union (aggregate) but memory-friendly (uses less memory and more processor time).
ST_PolygonizeST_PolygonizeAggCreates a GeometryCollection made up of Polygons from a set of Geometries which contain lines that represents the Polygons edges.
ST_UnionST_UnionAggReturns a Geometry object that represents the point set union of two Geometries.

2.5. Renamed Functions

H2 database doesn't support homonyms functions with the same number of parameters, even if those parameters have different types. For that reason, several functions have been renamed in H2. They are listed in the following table:

Renamed FunctionPostgreSQLH2
ST_MakePolygon

geometry ST_MakePolygon (bytea LineString);

geometry ST_MakePolygon (bytea LineString, bytea LineString);

geometry ST_MakePolygon (bytea LineString, bytea[] LineString Array);

geometry ST_MakePolygon (bytea LineString);

geometry ST_MakePolygon (bytea LineString, bytea LineString);

geometry ST_MakePolygonEx (bytea LineString, bytea[] LineString Array);

ST_Distance_Spheroid

double ST_Distance_Spheroid (bytea PointA, bytea PointB, integer SRID);

double ST_Distance_Spheroid (bytea PointA, bytea PointB);

double ST_Distance_Spheroid (bytea PointA, bytea PointB, varchar WKT_Spheroid);

double ST_Distance_SpheroidEx (bytea PointA, bytea PointB, integer SRID);

double ST_Distance_Spheroid (bytea PointA, bytea PointB);

double ST_Distance_Spheroid (bytea PointA, bytea PointB, varchar WKT_Spheroid);

ST_Length_Spheroid

geometry ST_Length_Spheroid (bytea LineString, varchar Spheroid);

geometry ST_Length_Spheroid (bytea LineString, integer SRID);

geometry ST_Length_Spheroid (bytea LineString);

geometry ST_Length_Spheroid (bytea LineString, varchar Spheroid);

geometry ST_Length_SpheroidEx (bytea LineString, integer SRID);

geometry ST_Length_Spheroid (bytea LineString);

ST_Length2D_Spheroid

geometry ST_Length2D_Spheroid (LineString, Spheroid);

geometry ST_Length2D_Spheroid (LineString, SRID);

geometry ST_Length2D_Spheroid (LineString);

geometry ST_Length2D_Spheroid (LineString, Spheroid);

geometry ST_Length2D_SpheroidEx (LineString, SRID);

geometry ST_Length2D_Spheroid (LineString);

ST_Length3D_Spheroid

geometry ST_Length3D_Spheroid (bytea LineString, varchar Spheroid);

geometry ST_Length3D_Spheroid (bytea LineString, integer SRID);

geometry ST_Length3D_Spheroid (bytea LineString);

geometry ST_Length3D_Spheroid (bytea LineString, varchar Spheroid);

geometry ST_Length3D_SpheroidEx (bytea LineString, integer SRID);

geometry ST_Length3D_Spheroid (bytea LineString)

ST_Buffer

geometry ST_Buffer (bytea Geometry, double distance);

geometry ST_Buffer (bytea Geometry, double distance, integer QuadrantSegments);

geometry ST_Buffer (bytea Geometry, double distance, varchar Buffer_Parameters);

geometry ST_Buffer (bytea Geometry, double distance);

geometry ST_Buffer (bytea Geometry, double distance, integer QuadrantSegments);

geometry ST_BufferEx (bytea Geometry, double distance, varchar Buffer_Parameters);

Functions without alias

The functions Difference and Expand are already defined in the H2 database. So, if you want to use those JASPA functions, you must always call the functions with the "ST_" prefix.

PostgreSQLH2
ST_Difference, DifferenceST_Difference
ST_Expand, ExpandST_Expand
ST_PointST_Point, Point