fetching cursor records in to a array throwing error - postgresql

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.

Related

How can I omit records when returning a table in postgresql?

I have a problem when I try to execute a function where, depending on the result of another function, it returns a record or not. What I want to do is that when the function ("function_typecar" in the example) returns 1 as a result, it returns the record, otherwise no. The problem is when the condition is not met. It repeats the same record until there is one that meets the condition again. Is there a way to skip returning the records when the condition is not met? I leave an example of this situation
CREATE OR REPLACE FUNCTION schema.function_test
RETURNS TABLE(id_r INTEGER, name_r CHARACTER VARYING, year_r INTEGER) AS
$BODY$
DECLARE
sql_record RECORD;
type_car INTEGER;
BEGIN
SELECT id, name, year
FROM car
FOR sql_record IN
SELECT id, name, year
FROM car
LOOP
SELECT type INTO type_car FROM function_typecar(sql_record.id);
IF type_car = 1 THEN
id_r := sql_record.id;
name_r := sql_record.name;
year_r := sql_record.year;
END IF;
RETURN NEXT;
END LOOP;
END; $BODY$
This is the result that I want to avoid and that only brings me those that meet the IF condition:
Something like this should work, without a LOOP and in plain SQL:
CREATE OR REPLACE FUNCTION function_test()
RETURNS TABLE(id_r INTEGER, name_r CHARACTER VARYING, year_r INTEGER)
LANGUAGE SQL
AS
$BODY$
SELECT id, name, year
FROM car
JOIN function_typecar(id) ON type = 1;
$BODY$;

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

Function returns only one column when return type is record type postgres

I have a function that has the return type of record.
Below is the function am using, basically what the function does is , it takes in input paramter and queries the database to return the columns:
drop function if exists test_proc(sr_number1 bigint);
create or replace function test_proc(sr_number1 bigint) RETURNS record /*SETOF tbl*/ AS $$
declare
i integer default 0;
record_type record;
begin
select sr_num,product_number,phone,addr into record_type from my_table where sr_num=sr_number1;
return record_type;
end
$$ LANGUAGE plpgsql;
Unfortunately, when I execute the function as
select test_proc(12345); I get the result as a comma separated list in just one column like (sr_num,product_number,phone,addr). But what I was hoping to have it return was a table row with the column values and their respective column names.
I also tried executing the function as
select * from test_proc(12345); but get the following error
ERROR: a column definition list is required for functions returning "record"
When querying a function that returns a record you must specify the type of record you want to get in the result
select * from test_proc(12345) f(b bigint, t text);
This should work.
A better solution is to declare the type of record in the function
CREATE OR REPLACE FUNCTION test_proc(sr_number1 bigint)
RETURNS TABLE(b bigint, t text) AS $$ $$

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