How can I debug this function with v_operation and v_message? - postgresql

CREATE OR REPLACE FUNCTION f_sync_from_xml()
RETURNS boolean AS
$BODY$
DECLARE
myxml xml;
datafile text := 'Documenti/ABBATE_EMANUELE_Lvl1F2Va_20160418-1759.xml';
BEGIN
myxml := pg_read_file(datafile, 0, 100000000);
CREATE TABLE tmp AS
SELECT (xpath('//some_id/text()', x))[1]::text AS id
FROM unnest(xpath('/xml/path/to/datum', myxml)) x;
END;
$BODY$ language plpgsql;
SELECT * from tmp;
This function should allow to transform a XML into postgres table. This function doesn't give an error but not create the table. How can I use v_operation and/or v_message to find possible errors?

Related

how to handle refcursor not retrieving data in PGSQL

How to handle refcursor not retrieving data(empty resultset) in PGSQL?
create or replace function function_1( In tblname varchar(15))
returns refcursor
language plpgsql
as $$
declare
v_cnt integer;
r_ref refcursor='ref2';
v_sql text='select * from tbl where 1=2';--default statement;shld return empty if
--input is invalid
begin
if tblname ilike 'scientist' then
v_sql:='select * from tbl'; --table name 1
end if;
open r_ref for
execute v_sql;
return r_ref;
end;
$$;
Is there any other way to handle without using dynamic sql?
execution: Test case 1 : should return empty result set
select * from function_1('invalid');
fetch all in "ref2";
execution: Test case 2 : should return proper data from able
select * from function_1('scientist');
fetch all in "ref2";
Thanks
You don't need a dynamic query when you only have one test case to cover = 'scientist'. In this case, you can simply do :
create or replace function function_1( In tblname varchar(15))
returns setof scientist language plpgsql as $$
begin
if tblname ilike 'scientist' then
return query
select * from scientist ;
end if;
end;
$$;

Trigger doesn't work and doesn't show any errors

I'm trying to create a trigger that will shorten the name and the middle name to initials.
That's what i have:
CREATE OR REPLACE FUNCTION myfunc() RETURNS TRIGGER AS $$
DECLARE nm VARCHAR(50);
DECLARE mdnm VARCHAR(50);
BEGIN
nm = LEFT(NEW.name, 1);
mdnm = LEFT(NEW.middle_name, 1);
SET NEW.name = nm;
SET NEW.middle_name = mdnm;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER table_before_insert BEFORE INSERT OR UPDATE ON table1
FOR EACH ROW EXECUTE PROCEDURE myfunc();
But for some reasons it doesn't work, what can it be?
As documented in the manual variables are assigned with := or =. But not with the SET command - which changes configuration properties. You also don't need a separate DECLARE block for each variable:
So your trigger function should look like this:
CREATE OR REPLACE FUNCTION myfunc() RETURNS TRIGGER AS $$
DECLARE
nm VARCHAR(50);
mdnm VARCHAR(50);
BEGIN
nm := LEFT(NEW.name, 1);
mdnm := LEFT(NEW.middle_name, 1);
NEW.name := nm;
NEW.middle_name := mdnm;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
You don't even need the variables:
CREATE OR REPLACE FUNCTION myfunc() RETURNS TRIGGER AS $$
BEGIN
NEW.name := LEFT(NEW.name, 1);
NEW.middle_name := LEFT(NEW.middle_name, 1);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

How to initialize row datatype variables?

I would like to create a function that initialize and return the row datatype of a table as
CREATE FUNCTION get_default_table_row_object()
RETURNS mytable AS $$
DECLARE
row mytable;
BEGIN
row.field1 := 0;
row.field2 := -1;
row.record_reg_id := 1;
row.record_upd_id := 1;
row.record_reg_date := current_timestamp;
row.record_upd_date := current_timestamp;
RETURN row;
END;
$$ LANGUAGE plpgsql;
becuase my table has alot of columns and I need to create dozens of variables at several functions. I would like to use above function as
CREATE FUNCTION some_function() RETURNS VOID AS $$
DECLARE
i_obj1 mytable := get_default_table_row_object(); -- declare and initialize default values
BEGIN
-- function body
END;
$$ LANGUAGE plpgsql;
But this give me the error ERROR: default value for row or record variable is not supported. Has someway to figure it out ?
You can set it in the body instead, like so:
CREATE FUNCTION some_function() RETURNS VOID AS $$
DECLARE
i_obj1 mytable; -- declare only
BEGIN
i_obj1 := get_default_table_row_object(); -- set default values
END;
$$ LANGUAGE plpgsql;

How can I load an XML local file to postgres without pg_read_file?

CREATE OR REPLACE FUNCTION j_f_sync_from_xml()
RETURNS boolean AS
$BODY$
DECLARE
myxml xml;
datafile text := 'ABBATE_EMANUELE.xml';
BEGIN
myxml := pg_read_file(datafile, 0, 100000000);
CREATE TABLE james AS
SELECT (xpath('//some_id/text()', x))[1]::text AS id
FROM unnest(xpath('/xml/path/to/datum', myxml)) x;
END;
$BODY$ language plpgsql;
pg_read_file doesn't function because i can't write on server machine.
Anyone has the idea how to use a local file in postgres?
using psql:
create table xml(body text);
\copy xml from 'C:\temp\notes.xml';
select string_agg(body,'')::xml from xml;
results:
string_agg
------------------------------------------------------------------------------------------------------------------
<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>
or same with pgadmin:
after that same:
select string_agg(body,'')::xml from xml;

Using OUT parameters in Postgres Stored Procedure

Is there any way I can set some value to OUT parameter in Postgres stored procedure? Below is the example what I want to do. In oracle PL/SQL you can use out parameters and set it to any value and return it. After that u can use that value and manipulate it.
CREATE OR REPLACE FUNCTION demo_procedure(p_invoice text, OUT p_out1 integer, OUT p_out2 integer)
returns SETOF record
as
$func$
DECLARE
s_inv_rest integer;
s_state integer;
BEGIN
BEGIN
SELECT "REST_TO_PAY", "STATE"
INTO s_inv_rest, s_state
FROM "INVOICE"
WHERE "INVOICE_REFERENCE" = p_invoice;
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_out1 := 1;
p_out2 := 2;
RETURN;
END;
END;
$func$
language plpgsql;
So in this example for instance if no data is found I want to return some out code and out message.