SQL state: 22P02 invalid input syntax for integer error in recursive PL/pgSQL function - postgresql

I am new to PostgreSQL and I am currently in the process of writing a recursive function to find tram times.
I have defined a custom type as:
CREATE TYPE single_journey AS
(tram_id integer,
departure_station text,
departure_time time without time zone,
destination_station text,
arrival_time time without time zone);
and the function...
CREATE OR REPLACE FUNCTION find_tram_same_line(text, text, time) returns single_journey AS $$
DECLARE
departure_station ALIAS FOR $1;
destination_station ALIAS FOR $2;
query_time ALIAS FOR $3;
journey single_journey;
BEGIN
journey.departure_station := departure_station;
journey.destination_station := destination_station;
SELECT tram_id, time
INTO journey.tram_id, journey.departure_time
FROM station_departure_times
JOIN stations on station_departure_times.station_id = stations.station_id
WHERE stations.name = departure_station
AND time > query_time
ORDER BY time ASC
LIMIT 1;
SELECT time
INTO journey.arrival_time
FROM station_departure_times
JOIN stations on station_departure_times.station_id = stations.station_id
WHERE stations.name = destination_station
AND tram_id = journey.tram_id;
IF journey.arrival_time IS NULL THEN
SELECT find_tram_same_line(
departure_station,
destination_station,
(query_time + interval '1 minute'))
INTO journey;
END IF;
RETURN journey;
END;
$$ LANGUAGE plpgsql;
The query:
SELECT find_tram_same_line('GrimesDyke', 'CitySquare', '09:00:00');
Whenever I run the query, I get an error:
********** Error **********
ERROR: invalid input syntax for integer: "(24,GrimesDyke,09:07:00,CitySquare,10:19:00)"
SQL state: 22P02
Context: PL/pgSQL function find_tram_same_line(text,text,time without time zone) line 29 at SQL statement
I have spent some time trying to figure out why this is to no avail. The only integer in the single_journey type is the tram_id but I am unsure why this is causing an issue. Does anyone know why this might be?
Edit: Should be noted that (24,GrimesDyke,09:07:00,CitySquare,10:19:00) is what I was expecting.

Related

calling plpy.execute in PL/Python much slower than calling Execute in PL/pgsql

I have written the same function in PL/PgSQL and PL/Python:
create function pythontest2()
returns TABLE(id bigint, timestamp_ timestamp without time zone, acknowledgedtimestamp timestamp without time zone, inactivetimestamp timestamp without time zone)
language plpython3u
as
$$
tablename = "dimension_alarms"
columns = ["id", "timestamp as TimeStamp_", "acknowledgedtimestamp", "inactivetimestamp"]
query_string = "select {0} from {1}".format(", ".join(columns), tablename)
return plpy.execute(query_string)
$$;
create function pythontest3() returns text
language plpython3u
as
$$
tablename = "dimension_alarms"
columns = ["id", "timestamp as TimeStamp_", "acknowledgedtimestamp", "inactivetimestamp"]
return "select {0} from {1}".format(", ".join(columns), tablename)
$$;
create function pythontest3execute()
returns TABLE(id bigint, timestamp_ timestamp without time zone, acknowledgedtimestamp timestamp without time zone, inactivetimestamp timestamp without time zone)
language plpgsql
as
$$
BEGIN
RETURN QUERY EXECUTE pythonTest3();
RETURN;
END
$$;
When I call select pythontest3execute(); and select pythonTest2();, the first statement executes in half the time of the second.
The first function calls "Execute" from a PL/PqSQL function, the second function calls plpy.execute(...). Both functions use the python interpreter to execute, so why is plpy.execute() in particular so slow?
Edit:
The average time it took to execute pythonTest2() was around 200ms, and the average time it took pythonTest3Execute() was about 80ms. The query returns around 150,000 results

no function matches the given name and argument types. you might need to add explicit type casts. INSERT on PREPARE

I have this PL/pgSQL function.
CREATE OR REPLACE FUNCTION add_employee_att(emp_id INT, att_time TIMESTAMP)
RETURNS void AS $$
BEGIN
IF NOT EXISTS (SELECT FROM employee_att WHERE employee_id = emp_id AND time_stamp = att_time) THEN
PREPARE prep_att (INT, TIMESTAMP)
AS INSERT INTO employee_att (employee_id, time_stamp) VALUES ($1, $2);
EXECUTE prep_att (emp_id, att_time);
END IF;
END;
$$ LANGUAGE plpgsql;
Then if i execute this:
SELECT add_employee_att(35, '2019-08-29 00:00:25'::timestamp);
I got this error:
Error in query: ERROR: function prep_att(integer, timestamp without time zone) does not exist
LINE 1: SELECT prep_att(emp_id, att_time)
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
QUERY: SELECT prep_att(emp_id, att_time)
CONTEXT: PL/pgSQL function add_employee_attendant(integer,timestamp without time zone) line 6 at EXECUTE
But if replace the PREPARE with this INSERT:
INSERT INTO employee_att (employee_id, time_stamp) VALUES (emp_id, att_time);
It works fine. Any idea what's wrong on the PREPARE stuff ?
Don't use PREPARE in plpgsql. It has not sense. Any embedded SQL is already prepared (execution plan is reused).
So write just
CREATE OR REPLACE FUNCTION add_employee_att(emp_id INT, att_time TIMESTAMP)
RETURNS void AS $$
BEGIN
IF NOT EXISTS (SELECT FROM employee_att
WHERE employee_id = emp_id
AND time_stamp = att_time)
THEN
INSERT INTO employee_att (employee_id, time_stamp) VALUES (emp_id, att_time);
END IF;
END;
$$ LANGUAGE plpgsql;
Attention: this test is example of typical code that is partially useless. It is not protection against duplicates (emp_id, att_time). Only unique index is it. You cannot to know ever, if you see last data. Every time, when you are using SQL, you are working with snapshot of database. But data inside database can be little bit different already.

Passing timestamp parameter to function in Postgresql 10.6

I'm building this function:
CREATE OR REPLACE FUNCTION qradar21(cliente_in VARCHAR(50), fecha_inicio timestamp, fecha_fin timestamp) RETURNS TABLE(empresa varchar, fecha timestamp, fuente text, total float) AS $$
BEGIN
RETURN QUERY
SELECT qradar_eventos_detalle.empresa, qradar_eventos_detalle.fecha, eventos->>'fuente' AS fuente, sum((eventos->>'total')::float) AS total FROM public.qradar_eventos_detalle
WHERE qradar_eventos_detalle.empresa = 'cliente_in'
AND qradar_eventos_detalle.fecha BETWEEN 'fecha_inicio' AND 'fecha_fin'
GROUP BY qradar_eventos_detalle.empresa, qradar_eventos_detalle.fecha, qradar_eventos_detalle.eventos
ORDER BY total DESC;
END;
$$ LANGUAGE plpgsql
And calling it with:
SELECT * FROM qradar21('BancoXXX', '2018-12-29 12:00:00', '2019-03-03 07:00:00');
Getting this message:
ERROR: invalid input syntax for type timestamp: «fecha_inicio»
LINE 3: AND qradar_eventos_detalle.fecha BETWEEN 'fecha_inicio' A...
If I change the function to use directly the date (AND qradar_eventos_detalle.fecha BETWEEN '2018-12-29 12:00:00' AND '2018-12-30 07:00:00'), it works great.
I don't know what I'm doing wrong... Does anyone know how to pass this "timestamp without time zone" format to the function?
Thank you in advance
Your function uses string literals, rather then referencing the parameters.
You need to remove the single quotes around your parameter names:
WHERE qradar_eventos_detalle.empresa = cliente_in --<< no quotes here!
AND qradar_eventos_detalle.fecha BETWEEN fecha_inicio AND fecha_fin
^
or here
When you call it, it's also better to use proper timestamp literal:
SELECT *
FROM qradar21('BancoXXX', timestamp '2018-12-29 12:00:00', timestamp '2019-03-03 07:00:00');

Run text as a query

I have a table with 2 columns . The first a serial and the 2nd is a query that stored as a text.
To more simple the question , at the end: I wish to create a function which I will enter the number of the serial as a parameter and the function will return me the result of the query which is found in the 2nd column.
I know I have to use the command 'execute' from other questions I saw here on stack.
Even before the end result, I made this simple function:
CREATE OR REPLACE FUNCTION public.try1()
RETURNS TABLE(datery timestamp without time zone)
LANGUAGE plpgsql
AS $function$
declare
stmt text;
BEGIN
stmt :='SELECT b FROM chks where a=4';
RETURN QUERY
execute stmt ;
END
$function$
The result of this query select b form chks where a=4 is:
'select now()::timestamp without time zone'
When I am running the function I get cast error which tells me the reutrn of th fuction is varchar and not timestamp and if I change the return type to varchar I get as a result the query itself and not the result of the query.
What am I missing here?
In any case, is there a more simple way to do this?
I am asking this both for my simple function and for the function with the parameter I have mentioned before.
Try something like this:
CREATE OR REPLACE FUNCTION public.try1(query_number numeric)
RETURNS TABLE(datery timestamp without time zone)
AS $function$
DECLARE
stmt text;
BEGIN
SELECT b INTO stmt
FROM chks
WHERE a=query_number;
RETURN QUERY EXECUTE stmt;
END
$function$
LANGUAGE plpgsql STRICT;

Integer array in plpgsql throws error in PostgreSQL 9.1 but works in 9.3

I have this function:
CREATE OR REPLACE FUNCTION check_presence_row(
_id_att_files integer[],
_people_name character varying,
_people_id character varying,
_time_start timestamp without time zone,
_time_end timestamp without time zone
)
RETURNS integer[] AS $BODY$
DECLARE
ids integer array;
BEGIN
ids := (SELECT "id_att_file"FROM att_presence WHERE
"id_att_file" = ANY ("_id_att_files") AND
"id_people" = get_people(
"_people_id",
"_people_name") AND
"time_start" = "_time_start" AND
"time_end" = "_time_end");
RETURN ids;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
When i call it in PostgreSQL version 9.3 this way:
SELECT check_presence_row(
CAST ('{1,4}' AS int[]),
CAST ('Random Guy' AS varchar),
CAST ('D0388A' AS varchar),
CAST ('2014/08/23 8:04:00' AS timestamp without time zone),
CAST ('2014/08/23 8:34:00' AS timestamp without time zone)
);
it runs OK and return result as desired, but on 9.1 when i send the same query it throws an error:
ERROR: array value must start with "{" or dimension information
CONTEXT: PL/pgSQL function "check_presence_row" line 5 at assignment
********** Error **********
ERROR: array value must start with "{" or dimension information
SQL state: 22P02
Context: PL/pgSQL function "check_presence_row" line 5 at assignment
I found out that when any of the input values of that array is exactly 1 it fails this way but if I change them to some different integer value the pass.... but only on my localhost. Our production server still fails to pass with any value. We tried another computer and that one pass even if the values are 1. Any ideas?
False alert, I just found out that it was caused by that ids := assignment. Because I had one row with id = 1 in att_file table it went wrong on my localhost, while on another computer with empty DB does not. I changed the return to not pass that variabile but only query instead:
CREATE OR REPLACE FUNCTION check_presence_row(
_id_att_files integer[],
_people_name character varying,
_people_id character varying,
_time_start timestamp without time zone,
_time_end timestamp without time zone
)
RETURNS SETOF integer AS
$BODY$
BEGIN
RETURN QUERY SELECT "id_att_file"FROM att_presence WHERE
"id_att_file" = ANY ("_id_att_files") AND
"id_people" = get_people(
"_people_id",
"_people_name") AND
"time_start" = "_time_start" AND
"time_end" = "_time_end";
END;$BODY$
LANGUAGE plpgsql