Insert Function Postgresql how to test with parameters? - postgresql

I have the following insert function in postgresql 9.4.
I am totally unable to test it with parameters.
DROP FUNCTION "Public".cash_inserts(integer, bigint, timestamp without time zone, character varying, numeric, numeric);
CREATE OR REPLACE FUNCTION "Public".cash_inserts(
cashid integer,
cashserial bigint,
cashdate timestamp without time zone,
cashmemo text,
cashcredit numeric,
cashdebit numeric)
RETURNS integer AS
$BODY$
INSERT INTO "Public"."CashAccounts"
VALUES
(
CashId,
CashSerial,
CashDate,
CashMemo,
CashCredit,
CashDebit
) RETURNING CashId ;
$BODY$
LANGUAGE sql VOLATILE
COST 100;
ALTER FUNCTION "Public".cash_inserts(integer, bigint, timestamp without time zone, text, numeric, numeric)
OWNER TO robert100;
Because the fields 'cashid,cashserial,cashdate' are either auto-incrementing or created by the database, I did not enter any values. However, Cashmemo is'Not NUll' and 'Cashcredit,Cashdebit' are nullable or optional.

Why include cashid,cashserial,cashdate in the function insert statement if they are either auto-incrementing or created by the database as you said and the function returns int?
Maybe try:
DROP FUNCTION "Public".cash_inserts(integer, bigint, timestamp without time zone, character varying, numeric, numeric);
CREATE OR REPLACE FUNCTION "Public".cash_inserts(
cashmemo text,
cashcredit numeric,
cashdebit numeric)
RETURNS integer AS
$BODY$ INSERT INTO "Public"."CashAccounts"
VALUES
(
CashMemo,
CashCredit,
CashDebit
) RETURNING CashId ; $BODY$
LANGUAGE sql VOLATILE
COST 100;
ALTER FUNCTION "Public".cash_inserts(text, numeric, numeric)
OWNER TO robert100
Then call the function with the variable parameters and cashid, cashserial and cashdate will be auto generated by the database.

It appears my original question was correct.What I discovered is that when you supply parameters, they must all be in quotes like this:
SELECT "Public".cash_inserts(
'10',
'4',
'12-12-12',
'COOL',
'200',
'300'
);

Related

Structure of query does not match function result type in plpgsql function

CREATE
OR REPLACE FUNCTION public.sp_production_snapshot(periodid integer, flagdc integer) RETURNS TABLE(
prod_period_id integer,
period character varying,
nosp character varying,
policy_no character varying,
policy_name character varying,
status_id integer,
pol_status character varying,
family_bisnis character varying,
tahun_ke integer,
year_comm integer,
payment integer,
plan_code character varying,
life_premium double precision,
rider_premium double precision,
extra_premium double precision,
total_premium double precision,
mop integer,
ccy_code character varying,
ccy_rate double precision,
post_date date,
commence_date date,
issue_date date,
stream_start_date date,
due_date date,
app_code character varying,
policy_cat character varying,
apcrd_a_amt double precision,
apcrd_b_amt double precision,
apcrd_d_amt double precision,
fyip_credit_amt double precision,
comm_npk_id integer,
comm_npk integer,
comm_npk_name character varying,
comm_rank_id integer,
comm_rank_code integer,
comm_rank_name character varying,
) LANGUAGE plpgsql AS $function$ BEGIN RETURN QUERY . . . . . . . . .
;
When I'm running it like this:
select * from sp_production_snapshot(865, 1);
I get the error:
SQL Error [42804]: ERROR: structure of query does not match function result type
Detail: Returned type bigint does not match expected type integer in column 1.
Where: PL/pgSQL function sp_production_snapshot(integer,integer) line 3 at RETURN QUERY
What is wrong with my script? I just migrated from gorm v1 to gorm v2. Before everything was fine, but many things break after moving to gorm v2.
Your statement after RETURN QUERY in the function body is likely selecting an identifier defined as bigint/bigserial type. It's not always safe to assume that this bigint value will map to your output integer because bigint can accommodate a higher values than integer can. From the documentation:
integer can be anything from -2147483648 to +2147483647
bigint can go from -9223372036854775808 to +9223372036854775807
bigserial can go from +1 to +9223372036854775807
If you stumbled upon a prod_period_id of 2147483648, you'd get an ERROR: integer out of range. To fix this you need to change the output types of your function accordingly:
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer, --should be bigint too if it corresponds to prod_period_id
flagdc integer)
RETURNS TABLE(
prod_period_id bigint,--change from integer to bigint
period character varying,
...
Depending on the structure of your RETURN QUERY and its sources, it's likely that it won't be the only output integer value you'll have to change to bigint. Note that you'll have to furst DROP then re-CREATE the function to avoid ERROR: cannot change return type of existing function thrown if you tried CREATE OR REPLACE instead.
If your output table follows the structure of some other table, instead of copying that into the function output table definition, you can use LIKE syntax:
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer,
flagdc integer)
RETURNS TABLE (LIKE your_table_schema.your_table_name) as
$function$
...
$function$ language plpgsql;
or RETURNS SETOF:
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer,
flagdc integer)
RETURNS SETOF your_table_schema.your_table_name language plpgsql as
$function$
...
$function$;
Also, if all you do is return a query, without using PL/pgSQL variables, loops, exception handling, you can stick with plain LANGUAGE SQL for better performance thanks to inlining. If all it does is look things up elsewhere, without modifying anything, it might be worth it to also make it STABLE and PARALLEL SAFE to enable better optimisation and execution planning.
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer,
flagdc integer)
RETURNS SETOF your_table_schema.your_table_name
STABLE PARALLEL SAFE LANGUAGE SQL AS
$function$
SELECT * FROM your_table_schema.your_table_name AS a
WHERE a.prod_period_id = $1 AND a.flagdc = $2;
$function$;

Postgres function input parameter as TEXT Array problem

My Table looks like
CREATE TABLE dev.clbk_logs
(
id bigint NOT NULL,
clbk_typ character varying(255) COLLATE pg_catalog."default",
clbk_json json,
cre_dte timestamp without time zone,
ld_id bigint,
ld_num character varying(255) COLLATE pg_catalog."default",
mod_dte timestamp without time zone,
CONSTRAINT clbk_logs_pkey PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
My function is
CREATE OR REPLACE FUNCTION dev.my_method(p_callback_types TEXT[], p_days_ago INT)
RETURNS SETOF dev.clbk_logs
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
return query
SELECT * FROM dev.clbk_logs
WHERE (clbk_Typ::TEXT) IN (($1)) AND (current_date - cre_dte::date)< p_days_ago;
END;
$BODY
Can someone please help what is wrong in above, and should make expected result.
I wanted to pass an array of string and in query.
Error I am getting is
LINE 2: WHERE (clbk_Typ::TEXT) IN (($1)) AND (current_date - cre_...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
QUERY: SELECT * FROM dev.clbk_logs
WHERE (clbk_Typ::TEXT) IN (($1)) AND (current_date - cre_dte::date)< p_days_ago
CONTEXT: PL/pgSQL function dev.my_method(text[],integer) line 3 at RETURN QUERY
SQL state: 42883
You need to use = any() not IN with an array.
The cast to ::text is also not needed. And for readability I would recommend using the parameter name, rather than the number:
CREATE OR REPLACE FUNCTION dev.my_method(p_callback_types TEXT[], p_days_ago INT)
RETURNS SETOF dev.fourkites_clbk_logs
LANGUAGE plpgsql
AS $BODY$
BEGIN
return query
SELECT *
FROM dev.fourkites_clbk_logs
WHERE clbk_Typ = any (p_callback_type)
AND (current_date - cre_dte::date) < p_days_ago;
END;
$BODY
Note that your condition on cre_dte can't use an index if you ever create one. If you want that condition to be able to use an index, change it to:
and cre_dte >= current_date - p_days_ago;

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

Type double does not exist in PostgreSQL

I have table like this:
CREATE TABLE workingtime_times
(
workingno serial NOT NULL,
checktime character(6) NOT NULL,
timeoffset double precision DEFAULT 9
)
I create function like this:
CREATE OR REPLACE FUNCTION MyFName()
RETURNS TABLE(
CheckTime character varying,
TimeOffset double
) AS
$BODY$
BEGIN
RETURN QUERY
SELECT t.CheckTime, t.TimeOffset
FROM WorkingTime_Times t
ORDER BY t.WorkingNo DESC
limit 1;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION MyFName()
OWNER TO postgres;
It make an error like this:
type double does not exist
Why we can create an table with column datatype double but return in the function fail. What type we can return in this case?
The name of the type is DOUBLE PRECISION and not just DOUBLE. Thus, your function header should look like this:
CREATE OR REPLACE FUNCTION MyFName() RETURNS TABLE(
CheckTime CHARACTER VARYING, TimeOffset DOUBLE PRECISION
) AS
You may also use type references:
CREATE OR REPLACE FUNCTION MyFName() RETURNS TABLE(
CheckTime working_intems.checktime%TYPE,
TimeOffset workingtime_times.timeoffset%TYPE
) AS

Syntax error in postgresql function

I am a beginner for postgresql and I would like to create a procedure in sql.
I created a function that inserts a record into a table and it returns the id.
But there is something wrong, I don't want any result except for the output parameter.
CREATE OR REPLACE FUNCTION public."InsertVideo"
(
OUT out_scope_id integer,
IN in_youtubeidvideo varchar[],
IN in_title varchar,
IN in_rating double precision,
IN in_viewcount integer
)
RETURNS integer AS
$$
DECLARE
id INTEGER;
INSERT INTO Video
(
YoutubeIdVideo,
Title,
Rating,
ViewCount,
DataAdded,
ConvertedFlag,
SchedulingFlag
)
VALUES
(
in_youtubeidvideo,
in_title,
in_rating,
in_viewcount,
now(),
false,
false
);
SELECT id := CURRVAL(pg_get_serial_sequence('public.video','IDVideo'));
RETURN id;
$$
LANGUAGE 'sql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;
A SQL function can't use variables and you don't need them for this. Changed it to:
CREATE OR REPLACE FUNCTION public."InsertVideo" (
IN in_youtubeidvideo varchar[],
IN in_title varchar,
IN in_rating double precision,
IN in_viewcount integer
) RETURNS integer AS $$
INSERT INTO Video (
YoutubeIdVideo,
Title,
Rating,
ViewCount,
DataAdded,
ConvertedFlag,
SchedulingFlag
) VALUES (
in_youtubeidvideo,
in_title,
in_rating,
in_viewcount,
now(),
false,
false
);
SELECT CURRVAL(pg_get_serial_sequence('public.video','IDVideo'));
$$ LANGUAGE 'sql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;