I am defining a new data type tpointp
for storing trajectories of moving objects. One function associated to this data type is atPeriod(tpointp, tsrange)
which projects the full trajectory to a time period represented as a timestamp range (tsrange
).
CREATE FUNCTION atPeriod(tpointp, tsrange)
RETURNS tpointp
AS 'MODULE_PATHNAME', 'temporalp_at_period'
LANGUAGE C IMMUTABLE STRICT;
This function can be used in queries like the following one
EXPLAIN
SELECT atPeriod(Trip, Period) AS Trip
FROM QueryPeriods, berlinmod_trip
-- Call the temporal index if any
WHERE getTime(Trip) && Period
Nested Loop (cost=0.14..475.50 rows=898 width=32)
-> Seq Scan on queryperiods (cost=0.00..3.00 rows=100 width=24)
-> Index Scan using berlinmod_trip_temporal_gist_idx on berlinmod_trip (cost=0.14..2.30 rows=18 width=104)
Index Cond: (gettime(trip) && queryperiods.period)
As it is done in PostGIS, I would like to use inlining for implicitly calling any potential indexes. That would allow the user to remove the WHERE
clause in the above query. I rewrote the definition of the function atPeriod()
above as follows.
CREATE FUNCTION _atPeriod(tpointp, tsrange)
RETURNS tpointp
AS 'MODULE_PATHNAME', 'temporalp_at_period'
LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION atPeriod(tpointp, tsrange)
RETURNS tpointp
AS 'SELECT @extschema@._atPeriod($1,$2) WHERE getTime($1) OPERATOR(@extschema@.&&) $2'
LANGUAGE 'sql' IMMUTABLE;
However with the new definition there is no implicit index call
EXPLAIN
SELECT atPeriod(Trip, Period) AS Trip
FROM QueryPeriods, berlinmod_trip
Nested Loop (cost=0.00..47224.47 rows=179700 width=32)
-> Seq Scan on berlinmod_trip (cost=0.00..49.97 rows=1797 width=104)
-> Materialize (cost=0.00..3.50 rows=100 width=24)
-> Seq Scan on queryperiods (cost=0.00..3.00 rows=100 width=24)
In PostgreSQL there are several conditions to enable inlining SQL functions: https://wiki.postgresql.org/wiki/Inlining_of_SQL_functions
However, I was not able to understand why this doesn't work for the function atPeriod()
.
Notice that this works for boolean
functions. I have another function intersects()
which generalizes the ST_Intersects
topological operator:
CREATE OR REPLACE FUNCTION _intersects(tpointp, geometry)
RETURNS boolean
AS 'MODULE_PATHNAME', 'intersects_tpointp_geom'
LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION intersects(tpointp, geometry)
RETURNS boolean
AS 'SELECT trajectory($1) OPERATOR(@extschema@.&&) $2 AND @extschema@._intersects($1,$2)'
LANGUAGE 'sql' IMMUTABLE;
In this case implicit index calls are performed as shown in the following query.
EXPLAIN
SELECT *
FROM QueryRegions R, berlinmod_trip T
WHERE intersects(R.Geom, T.Trip)
Nested Loop (cost=0.14..278.50 rows=60 width=959)
-> Seq Scan on queryregions r (cost=0.00..13.00 rows=100 width=847)
-> Index Scan using berlinmod_trip_spatial_idx on berlinmod_trip t (cost=0.14..2.65 rows=1 width=112)
Index Cond: (r.geom && trajectory(trip))
Filter: _intersects(r.geom, trip)
Best Answer
I think you may be making this more complex then need be, two alternative methods of storing trajectories.
LINESTRING M
with eachPOINT M
'sM
dimension representing the offset sincet0
. This is the method that PostGIS standardizes around withST_IsValidTrajectory
,ST_DistanceCPA
, andST_AddMeasure
LINESTRING
: everyPOINT
on theLINESTRING
representst0 + numpoints-1
Both of those scheme can be indexed simply and easily.