2

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

1 Answer 1

5
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:

Sign up to request clarification or add additional context in comments.

5 Comments

I tried the sql one and got an error saying return type mismatch in function declared to return text[]. Actual return type is text. My query when just run as a query returns tons of records of type text. I changed the returns text[] to just text and it works but thats not what i'm looking for. I want a list of all of the results. I also tried the PL/pgSQL one and had issues. Got same result as my original. For the lines return QUERY and SELECT DISTINCT ...; Should I put return query there or is that where my query goes and do I have to put it in ()
@Jeremy: Without table definition in your question, how can I guess your column types? I added some pointers. Also for returning from a function. You can also find many examples in the [plpgsql] tag.
I assumed that by specifying that my return type was text that it meant that the data being returned was of type text I'm sorry. I did however manage to get my original query to work changing the returns text[] as $$ to returns setof text as $$ . Also had to change the language to sql.
@Jeremy: Oh, of course. SETOF was my oversight, sorry. That should have been clear from the beginning. Amended the answer.
The solution was a setof text not setof text[] but thanks for your help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.