Question

I tried creating a function that would return the contents of the below query where proto_location is of type text. Not sure if it matters but my java code that currently calls this query just reads each record as a string.

SELECT DISTINCT tm.proto_location
FROM track_message tm
WHERE tm.workflow_analytic_instance_id = 204
AND EXISTS ( SELECT *
    FROM track_message_to_track_mapping tm2tm
    JOIN track t ON t.id = tm2tm.track_id
    JOIN track_item ti ON t.id = ti.track_id
    JOIN track_point tp ON ti.id = tp.track_item_id
    WHERE tm.id =tm2tm.track_message_id
    AND ti.item_time BETWEEN 1328816277089000 AND 1328816287089000
    AND ST_Intersects
            (tp.track_position
            , ST_GeomFromText('POLYGON((-144 59, -41 46, -75 15, -127 25, -144 59))',4326)
            )
    )
    ;

Here is my function

CREATE OR REPLACE Function getTrackMessages(workflow bigint, start_time bigint, end_time bigint) returns text[]
as $$
SELECT DISTINCT tm.proto_location
FROM track_message tm
WHERE tm.workflow_analytic_instance_id = $1AND EXISTS ( SELECT *
    FROM track_message_to_track_mapping tm2tm
    JOIN track t ON t.id = tm2tm.track_id
    JOIN track_item ti ON t.id = ti.track_id
    JOIN track_point tp ON ti.id = tp.track_item_id
    WHERE tm.id =tm2tm.track_message_id
    AND ti.item_time BETWEEN $2 AND $3        AND ST_Intersects
            (tp.track_position
            , ST_GeomFromText('POLYGON((-144 59, -41 46, -75 15, -127 25, -144 59))',4326)
            )
    )
    ;
$$ Language 'plpgsql';

I keep getting an error saying Syntax error at or near "select" and its refering to the line

SELECT DISTINCT tm.proto_location
Was it helpful?

Solution

CREATE OR REPLACE FUNCTION get_track_messages(workflow bigint, start_time bigint, end_time bigint)
  RETURNS SETOF text
  LANGUAGE sql AS
$func$
SELECT DISTINCT tm.proto_location
FROM   track_message tm
WHERE  tm.workflow_analytic_instance_id = $1
AND    EXISTS (
    SELECT FROM track_message_to_track_mapping tm2tm
    JOIN   track        t  ON t.id = tm2tm.track_id
    JOIN   track_item   ti ON t.id = ti.track_id
    JOIN   track_point  tp ON ti.id = tp.track_item_id
    WHERE  tm.id = tm2tm.track_message_id
    AND    ti.item_time BETWEEN $2 AND $3
    AND    ST_Intersects (tp.track_position
                        , ST_GeomFromText('POLYGON((-144 59, -41 46, -75 15, -127 25, -144 59))',4326))
    );
$func$;

Most importantly, it would work as sql function.
For a PL/pgSQL function you'd need to change more:

CREATE OR REPLACE FUNCTION get_track_messages(workflow bigint
                                            , start_time bigint
                                            , end_time bigint)
  RETURNS SETOF text
  LANGUAGE plpqsql AS
$func$
BEGIN
   RETURN QUERY
   SELECT DISTINCT ... ;
END
$func$;

If the query returns more than 1 row, you also need SETOF (as you figured out yourself). Call the function with:

SELECT * FROM get_track_messages( ... );

More about returning from a function in the manual.

Data type

proto_location is a character type. If you actually want to return an array of text (like your title states) you can aggregate like this:

SELECT array_agg(DISTINCT tm.proto_location) ...

And adapt the return type of the function to SETOF text[].

For a sorted array:

SELECT array_agg(DISTINCT tm.proto_location ORDER BY proto_location) ...

Or, to get a sorted list (text) instead of an array (text[]):

SELECT string_agg(DISTINCT tm.proto_location ORDER BY proto_location, ', ') ...

See:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top