PostgreSQL - Invalid input syntax for integer - postgresql

I have made composite type named t_user_type:
CREATE TYPE t_user_type AS
(uid integer,
firstname character varying,
lastname character varying,
companyname character varying,
email character varying,
sip_phone integer);
...and I need to cast string to that type, so I do
SELECT '(11423, FirstName, LastName, Company, email#gmail.com, 204)' :: t_user_type;
everythin is fine. No errors, nothing. But when I do that same thing using procedure, I get this error: Invalid input syntax for integer: "(11423," FirstName"," LastName"," Company"," email#gmail.com", 204)".
Here is my procedure:
CREATE OR REPLACE FUNCTION change_type(p_user character varying)
RETURNS void AS
$BODY$DECLARE
v_user_type t_user_type;
BEGIN
SELECT p_user :: t_user_type INTO v_user_type;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION change_type(character varying)
OWNER TO postgres;
And here is query that uses the procedure:
SELECT change_type(
'(11423, FirstName, LastName, Company, email#gmail.com, 204)');
Can anybody tell me what am I doing wrong?

Not sure why that fails I made small change where I just cast the value into your local variable and it appears to work. But I don't know why yet. Is it legal to SELECT INTO a variable like you were doing(I think so I can do it with regular text string into a text variable)? I usually do it like my example below when it's just a variable with no source table.
CREATE TYPE t_user_type AS
(uid integer,
firstname character varying,
lastname character varying,
companyname character varying,
email character varying,
sip_phone integer);
SELECT '(11423, FirstName, LastName, Company, email#gmail.com, 204)' :: t_user_type;
CREATE OR REPLACE FUNCTION change_type(p_user character varying)
RETURNS t_user_type AS
$BODY$DECLARE
v_user_type t_user_type;
BEGIN
v_user_type := CAST(p_user AS t_user_type);
return v_user_type;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION change_type(character varying)
OWNER TO postgres;
SELECT change_type(
'(11423, FirstName, LastName, Company, email#gmail.com, 204)');

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

Not able to read values from xml in postgres

I am trying to read from a xml and insert them in a temporary table and return that table as a result. Below is the Postgres function I am trying with
CREATE OR REPLACE FUNCTION public.xml(
)
RETURNS TABLE(name character varying, description character varying, parentpid character varying, level integer, nodenumber character varying, displayorder integer, iscustom boolean)
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
declare
xmlvalue text := '<ArrayOfClientProcess>
<ClientProcess><Id>0</Id><IsActive>false</IsActive><LastModifiedBy>email</LastModifiedBy>
<LastModifiedOn>2022-04-27</LastModifiedOn><ClientId>0</ClientId><ProcessId>0</ProcessId>
<IsUserSelected>false</IsUserSelected><IndustryId>0</IndustryId><Occurrence>false</Occurrence><ParentPId>NULL</ParentPId>
<CAMSAssigned>false</CAMSAssigned><KPIAssigned>false</KPIAssigned><IsTechVariantAvailable>false</IsTechVariantAvailable>
<IBSCentralId>0</IBSCentralId><MasterId>0</MasterId><MasterCentralId>0</MasterCentralId><SegmentId>0</SegmentId><CAMId>0</CAMId>
<IsEPCAvailable>false</IsEPCAvailable><IsVariantAvailable>false</IsVariantAvailable><IsSubvariantAvailable>false</IsSubvariantAvailable>
<LOMVariantId>0</LOMVariantId><ProcessLevel>0</ProcessLevel><OperationsPresence>false</OperationsPresence><IsDigitalImpact>false</IsDigitalImpact>
<IsCrossIndustry>false</IsCrossIndustry><Name>FinanceCustom</Name><Description>Finance</Description><ParentId>0</ParentId><Level>0</Level>
<NodeNumber>0</NodeNumber><GeographyId>0</GeographyId><DisplayOrder>0</DisplayOrder><IsCustom>true</IsCustom><IsCustomMapped>false</IsCustomMapped>
<IsProcessChecked>false</IsProcessChecked><islinkedwithCPA>0</islinkedwithCPA><ProcessIdfromCPA>0</ProcessIdfromCPA>
<IsProcessCheckedOnLeftPane>false</IsProcessCheckedOnLeftPane></ClientProcess></ArrayOfClientProcess>';
begin
CREATE TEMPORARY TABLE tempClientProcess(name character varying,
description character varying,
parentpid character varying,
level integer,
nodenumber character varying,
displayorder integer,
iscustom boolean);
with data as (
select xmlvalue::xml val)
INSERT INTO tempClientProcess(name,description,parentpid,level,nodenumber,displayorder,iscustom)
SELECT d.name,d.description,d.parentpid,d.level,d.nodenumber,d.displayorder,d.iscustom
FROM data x,
XMLTABLE('/ArrayOfClientProcess/ClientProcess'
PASSING val
COLUMNS
name character varying PATH 'name',
description character varying PATH 'description',
parentpid character varying PATH 'parentpid',
level integer PATH 'level',
nodenumber character varying PATH 'nodenumber',
displayorder integer PATH 'displayorder',
iscustom boolean PATH 'iscustom') as d;
return query
select * from tempClientProcess ;
drop table tempClientProcess;
end;
$BODY$;
When i execute the function, the temporary table displays null as column values. Makes me think that it might not be able to read the values from xml properly. Something wrong I am doing while parsing maybe.
Assuming the invalid LastModifiedOn> is a copy & paste error, the error is in your XPATH expression for the columns. Tag names are case sensitive, so you need this column definition:
name character varying PATH 'Name',
description character varying PATH 'Description',
parentpid character varying PATH 'ParentPId',
level integer PATH 'Level',
nodenumber character varying PATH 'NodeNumber',
displayorder integer PATH 'DisplayOrder',
iscustom boolean PATH 'IsCustom'
Note that creating the temporary table in the function is completely unnecessary, you can return the result of xmltable() directly
CREATE OR REPLACE FUNCTION xml()
RETURNS TABLE(name character varying, description character varying, parentpid character varying, level integer, nodenumber character varying, displayorder integer, iscustom boolean)
LANGUAGE plpgsql
ROWS 1
AS $BODY$
declare
xmlvalue xml :=
'<ArrayOfClientProcess>
<ClientProcess><Id>0</Id><IsActive>false</IsActive><LastModifiedBy>email</LastModifiedBy>
<LastModifiedOn>2022-04-27</LastModifiedOn><ClientId>0</ClientId><ProcessId>0</ProcessId>
<IsUserSelected>false</IsUserSelected><IndustryId>0</IndustryId><Occurrence>false</Occurrence><ParentPId>NULL</ParentPId>
<CAMSAssigned>false</CAMSAssigned><KPIAssigned>false</KPIAssigned><IsTechVariantAvailable>false</IsTechVariantAvailable>
<IBSCentralId>0</IBSCentralId><MasterId>0</MasterId><MasterCentralId>0</MasterCentralId><SegmentId>0</SegmentId><CAMId>0</CAMId>
<IsEPCAvailable>false</IsEPCAvailable><IsVariantAvailable>false</IsVariantAvailable><IsSubvariantAvailable>false</IsSubvariantAvailable>
<LOMVariantId>0</LOMVariantId><ProcessLevel>0</ProcessLevel><OperationsPresence>false</OperationsPresence><IsDigitalImpact>false</IsDigitalImpact>
<IsCrossIndustry>false</IsCrossIndustry><Name>FinanceCustom</Name><Description>Finance</Description><ParentId>0</ParentId><Level>0</Level>
<NodeNumber>0</NodeNumber><GeographyId>0</GeographyId><DisplayOrder>0</DisplayOrder><IsCustom>true</IsCustom><IsCustomMapped>false</IsCustomMapped>
<IsProcessChecked>false</IsProcessChecked><islinkedwithCPA>0</islinkedwithCPA><ProcessIdfromCPA>0</ProcessIdfromCPA>
<IsProcessCheckedOnLeftPane>false</IsProcessCheckedOnLeftPane></ClientProcess>
</ArrayOfClientProcess>';
begin
return query
SELECT d.name,d.description,d.parentpid,d.level,d.nodenumber,d.displayorder,d.iscustom
FROM XMLTABLE('/ArrayOfClientProcess/ClientProcess'
PASSING xmlvalue
COLUMNS
name character varying PATH 'Name',
description character varying PATH 'Description',
parentpid character varying PATH 'ParentPId',
level integer PATH 'Level',
nodenumber character varying PATH 'NodeNumber',
displayorder integer PATH 'DisplayOrder',
iscustom boolean PATH 'IsCustom') as d;
end;
$BODY$;
In fact, you wouldn't even need PL/pgSQL for this. A simple language sql would do as well.

Syntax error at or near "IF" in PostgreSQL

I am trying to write an sql function on PostgreSQL, but I have an error with the 'IF':
ERROR: Syntax error at or near "IF"
LINE 11: IF Type = 's' THEN
I can't understand the syntax error.
(The Function without the IF work correctly)
My SQL Code:
CREATE OR REPLACE FUNCTION public.add_activity(IDactivity smallint,Date_Start date, Data_End date,
Type character varying,Name character varying DEFAULT NULL::character varying,
Typology character varying DEFAULT NULL::character varying, Client smallint DEFAULT NULL::smallint)
RETURNS void
LANGUAGE 'sql'
AS $BODY$
INSERT INTO public."Activity"
VALUES(IDactivity, Date_Start, Data_End, Type, Name);
IF Type = 's' THEN
INSERT INTO public."Service"
VALUES(IDactivity, Typology, Client);
END IF;
$BODY$;
Thank you!
IF is not implemented in the sql language but it is in the plpgsql language, see the manual.
You can either replace LANGUAGE sql by LANGUAGE plpgsql and then add BEGIN and END in the function body :
CREATE OR REPLACE FUNCTION public.add_activity(IDactivity smallint,Date_Start date, Data_End date,
Type character varying,Name character varying DEFAULT NULL::character varying,
Typology character varying DEFAULT NULL::character varying, Client smallint DEFAULT NULL::smallint)
RETURNS void
LANGUAGE plpgsql
AS $BODY$
BEGIN
INSERT INTO public."Activity"
VALUES(IDactivity, Date_Start, Data_End, Type, Name);
IF Type = 's' THEN
INSERT INTO public."Service"
VALUES(IDactivity, Typology, Client);
END IF;
END ;
$BODY$
Or you can change your code to stay in the sql language :
CREATE OR REPLACE FUNCTION public.add_activity(IDactivity smallint,Date_Start date, Data_End date,
Type character varying,Name character varying DEFAULT NULL::character varying,
Typology character varying DEFAULT NULL::character varying, Client smallint DEFAULT NULL::smallint)
RETURNS void
LANGUAGE sql
AS $BODY$
INSERT INTO public."Activity"
VALUES(IDactivity, Date_Start, Data_End, Type, Name);
INSERT INTO public."Service"
SELECT IDactivity, Typology, Client
WHERE Type = 's' ;
$BODY$

How to call Function within StoredProcedure in postgresql?

I created one function
select * from f_get_employees1();
I want to call this function in stored procedure .
I don't know why you need to call a function into procedure.You don't need to do this. Even then I give some reference, so you can understand what you want.
CREATE OR REPLACE PROCEDURE dbo.spForCustomerINfo(
p_name character varying DEFAULT ''::character varying,
p_mobile character varying DEFAULT ''::character varying,
p_email character varying DEFAULT ''::character varying,
p_password character varying DEFAULT ''::character varying,
p_dob timestamp(3))
LANGUAGE 'plpgsql'
AS $BODY$
Declare p_CurrentAge varchar(20);
begin
-- Get User Current Age
Select dbo.fnGetCurrentAgeOfuser(p_dob) into p_CurrentAge;
----- Insert User Data
insert into dbo.Customer(name,mobile,email,password,DOB,CurrentAge)
values(p_name,p_mobile,p_email,p_password,p_dob,p_CurrentAge);
commit;
end;
$BODY$;

I am having a data insertion problem in tables "pm_feature_id" is primary key from table and it interlinked with other 2 tables

I am having a data insertion problem in tables "pm_feature_id" is primary key from table and it interlinked with other 2 tables.the primary key is auto increment and it declared as variable, i am inserting the data in tables by using below the code"
i am inserting the data but i am trying to return the data "pm_feature_name,pm_component_id" by using select statement
-- FUNCTION: project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
-- DROP FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer);
CREATE OR REPLACE FUNCTION project.fn_insert_features(
featurename character varying,
compntid integer,
descrptn character varying,
helpfilename character varying,
mediatypeid integer,
accntemplyid integer)
RETURNS TABLE(pm_feature_name character varying, pm_component_id integer)
LANGUAGE "sql"
COST 100
VOLATILE
ROWS 1000
AS $BODY$
DECLARE
v_id integer;
BEGIN
Insert into project.pm_features
(pm_feature_name,pm_component_id,pm_description)values (featurename,compntid,descrptn)
RETURNING pm_feature_id INTO v_id;
Insert into project.pm_help_files
(component_feature_id,help_file_name, media_type_id)values (v_id,helpfilename,mediatypeid);
Insert into project.pm_point_of_contacts
(component_feature_id,pm_account_employee_id)values(v_id,accntemplyid);
select pm_feature_name,pm_component_id from project.pm_features
END;
$BODY$;
ALTER FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
OWNER TO pattesaadmin;
ERROR ERROR: syntax error at or near "integer" LINE 21: v_id integer;
^ SQL state: 42601 Character: 637
Try this out:
CREATE OR REPLACE FUNCTION project.fn_insert_features(
featurename character varying,
compntid integer,
descrptn character varying,
helpfilename character varying,
mediatypeid integer,
accntemplyid integer)
RETURNS TABLE(pm_feature_name character varying, pm_component_id integer)
LANGUAGE plpgsql
COST 100
VOLATILE
ROWS 1000
AS $BODY$
DECLARE
v_id integer;
BEGIN
Insert into project.pm_features
(pm_feature_name,pm_component_id,pm_description)values (featurename,compntid,descrptn)
RETURNING pm_feature_id INTO v_id;
Insert into project.pm_help_files
(component_feature_id,help_file_name, media_type_id)values (v_id,helpfilename,mediatypeid);
Insert into project.pm_point_of_contacts
(component_feature_id,pm_account_employee_id)values(v_id,accntemplyid);
return query select pm_features.pm_feature_name, pm_features.pm_component_id from project.pm_features;
END;
$BODY$;
ALTER FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
OWNER TO pattesaadmin;
Note that I changed "sql" to plpgsql and added "return query" in front of the select statement and a semicolon at the end of the statement.
Hopefully this will be enough, I don't have the table descriptions to test completely.
Best regards,
Bjarni