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

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

Related

fetching cursor records in to a array throwing error

When I execute the function below, I am getting the error:
date/time field value out of range: "0"
Could you please help me figure out what is wrong with this code.
This is thrown at FETCH c_dt_coursor INTO v_idetail;
create schema if not exists stbschema;
create type stbschema.itdtls as (
ID NUMERIC,
TD NUMERIC,
SDT TIMESTAMP(0),
RUP NUMERIC,
EDT TIMESTAMP(0)
);
do $$
begin
CREATE DOMAIN stbschema.itdtls_v as stbschema.itdtls[];
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
CREATE OR REPLACE FUNCTION stbschema.f1(p_ant numeric, p_dt timestamp without time zone, p_id numeric, p_dtf timestamp without time zone, p_tf character varying, OUT p_amount numeric, OUT p_sts boolean)
RETURNS record
LANGUAGE plpgsql
AS $function$
DECLARE
v_sts BOOLEAN := FALSE;
v_idetail stbschema.itdtls_v;
c_dt_coursor cursor is
select array(select row(id,
mny,
sdt,
rat,
coalesce(edt, p_dt))
from idtls
where id = p_id
and sdt <= p_dt
and coalesce(edt, p_dt) > p_dtf
order by sdt,mny);
begin
p_amount := 0;
OPEN c_dt_coursor;
FETCH c_dt_coursor INTO v_idetail;
CLOSE c_dt_coursor;
v_sts := TRUE;
p_sts := v_sts;
return;
end $function$;
An example row returned from the cursor is
{"(1,10,\"2001-01-01 00:00:00\",500,\"2009-01-01 12:00:00\")"}
Table stbschema.itdtls has a column of a date/time type, but the query in the cursor definition returns 0 for some field of the value where that is not possible.
An example would be
2019-00-01
So when PostgreSQL tries to cast the array to an array of stbschema.itdtls, it has to report an error.
Perhaps you can add a CASE expression to the query that replaces such values with a valid value.

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');

function does not exists in postgreSQL .. Why ?

Need your help please , can't understand why i got the following error , i am not a professional postgresql developer ..
As you can see the function created , so why the function not exist occurred ?
create or replace function loginAttempt (u_email character varying, u_password character varying, date_time timestamptz, OUT attempt smallint) returns smallint AS $$
BEGIN
INSERT INTO login_attempts (typed_password, date_time, attempt_nu, email) VALUES (u_password, date_time, attempt_nu, email);
IF attempt = 3 THEN INSERT INTO warnings (u_email,u_password) VALUES (u_email,u_password);
END IF;
END;
$$ LANGUAGE plpgsql;
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now(), 1);
ERROR: function loginattempt(unknown, unknown, timestamp with time zone, integer) does not exist
LINE 1: select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987',...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
SQL state: 42883
Character: 8
You have defined the last parameter as an OUT parameter, that means you can't pass a value for it.
You need to use:
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now());
As you are not writing to the parameter attempts I don't see a reason to define it as an out parameter to begin with. You can simply return the value if you need it:
create or replace function loginAttempt (u_email character varying, u_password character varying, u_date_time timestamptz, u_attempt smallint)
returns smallint
AS $$
BEGIN
INSERT INTO login_attempts (typed_password, date_time, attempt_nu, email)
VALUES (u_password, u_date_time, u_attempt, u_email);
IF u_attempt = 3 THEN
INSERT INTO warnings (u_email,u_password) VALUES (u_email,u_password);
END IF;
return u_attempt;
END;
$$ LANGUAGE plpgsql;
As the value 1 is assumed to be an integer, you need to cast that value when calling the function:
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now(), 1::smallint);
Online example: https://rextester.com/YNIQ55561

catching select query return value in postgresql function and use it

I want to execute this function. But it got error said
ERROR:
syntax error at or near ":="
LINE 7: select result:=MAX(path_history_id)as path INTO result from...
In this function I want to:
execute select with (MAX) and it will return maximum id from a table;
catch that value (it is an integer value);
put that value into last select query where condition.
I cant find a way in postgresql to do this.
CREATE OR REPLACE FUNCTION memcache(IN starting_point_p1 character varying, IN ending_point_p1 character varying)
RETURNS TABLE(path integer, movement_id_out integer, object_id_fk_out integer, path_history_id_fk_out integer, walking_distance_out real, angel_out real, direction_out character varying, time_stamp_out timestamp without time zone, x_coordinate_out real, y_coordinate_out real, z_coordinate_out real) AS
$BODY$
DECLARE result int;
BEGIN
select result:=MAX(path_history_id)as path INTO result from path_history_info where starting_point=starting_point_p1 and ending_point =ending_point_p1 and achieve='1';
return query
select * from movement_info where path_history_id_fk=result;
END;
$BODY$
LANGUAGE plpgsql
Syntax Error
The first query inside your function needs to be changed as follows:
select MAX(path_history_id)as path INTO result
from path_history_info
where starting_point=starting_point_p1
and ending_point =ending_point_p1 and achieve='1';
A single Query
You don't actually need a stored procedure for this. A single query can achieve the same result.
select * from movement_info where path_history_id_fk =
(SELECT MAX(path_history_id) FROM path_history_info
where starting_point=starting_point_p1
and ending_point =ending_point_p1 and achieve='1';

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

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.