ERROR: recursive inside the trigger function - postgresql

This my trigger that will trigger if new value is inserted in origin.
I want to store the result of recursive to table(extract).
I get this error
ERROR: syntax error at or near "perform"
LINE 10: perform * from "test";
^
SQL state: 42601
Character: 221
BEGIN
WITH RECURSIVE "test" as
(select "node_f", "node_2", "edge"
from "con" where "node_f"= new."origin"
union
select O."node_f", O."node_2", O."edge"
FROM "test" N
JOIN "con" O on O."node_f" = N."node_2")
Select * from "test";
INSERT INTO "extract"
SELECT * FROM "test";
return new;
END;

Related

Unable to return a table using CTE in postgresql

I am trying to create a CTE which establishes a parent child relationship and return the ids of the required childs. The Childs can also be the parent of their respective children. I have tried writing a postgresql function for that but I am facing an error, for which I am not able to understand the cause. Might be a very silly reason or syntax error, so far I have no clue. The error is 'ERROR: syntax error at or near "return"
LINE 22: return query
^
SQL state: 42601
Character: 472'
create or replace function fn_Get_All_Child_For_Process(
client_id integer,process_id integer,level integer)
returns table (id integer)
language 'plpgsql'
as
$$
begin
WITH CTE_Child AS
(
SELECT Id,level,ParentId
FROM ClientProcesses
WHERE ID = process_id and ClientId=client_id and Level < level
UNION ALL
SELECT t.Id,t.level,t.ParentId
FROM ClientProcesses t,CTE_Child C
where t.ParentID = C.ID and t.Level < level and t.ClientId=client_id
)
return query
SELECT C.Id FROM CTE_Child C where C.Id not in (process_id) ;
end;
$$;

How to implement dynamic sql function in postgresql?

I am using PostgreSQL 11 version.
I want to implement a function that takes the layer name (table), column name, and id as parameters.
create or replace function test(layer_name anyelement, field_name anyelement, object_id text)
returns setof anyelement
language plpgsql
as $function$
begin
return query execute format('
select
*
from
%s
where
%s = cast($1 as int4)'
, pg_typeof(layer_name), pg_typeof(field_name))
using object_id;
end;
$function$
;
This is the code I've implemented and when I call the function I get an error.
What am I doing wrong?
Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: syntax error at or near "="
Where: PL/pgSQL function test(anyelement,anyelement,text) line 3 at RETURN QUERY
### The error occurred while setting parameters
### SQL: select * from test(?, ?, ?)
### Cause: org.postgresql.util.PSQLException: ERROR: syntax error at or near "="
Where: PL/pgSQL function test(anyelement,anyelement,text) line 3 at RETURN QUERY
; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: syntax error at or near "="
Where: PL/pgSQL function test(anyelement,anyelement,text) line 3 at RETURN QUERY}
org.springframework.jdbc.BadSqlGrammarException:
### Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: syntax error at or near "="
Where: PL/pgSQL function test(anyelement,anyelement,text) line 3 at RETURN QUERY
### The error occurred while setting parameters
### SQL: select * from test(?, ?, ?)
### Cause: org.postgresql.util.PSQLException: ERROR: syntax error at or near "="
Where: PL/pgSQL function test(anyelement,anyelement,text) line 3 at RETURN QUERY
; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: syntax error at or near "="
Where: PL/pgSQL function test(anyelement,anyelement,text) line 3 at RETURN QUERY
You have to change your function slightly
Instead of field_name anyelement use field_name text in parameter.
and in place of pg_typeof(field_name) use only field_name:
So your function definition will be:
create or replace function test(layer_name anyelement, field_name text, object_id text)
returns setof anyelement
language plpgsql
as $function$
begin
return query execute format('
select
*
from
%s
where
%s = cast($1 as int4)'
, pg_typeof(layer_name), field_name)
using object_id;
end;
$function$
;
Most important part is calling of the function:
select * from test(null::table_name,'field_name','2');
Please note that your field_name always should be integer type and object_id should be number only because you are casting it to integer.
DEMO

Postgresql function table name parameter

I have n tables sharing a least one column name ("Date"), I want to create a function which can make a
select column1, column2, ..., columnx from myfunction('table_name','date_value')
First, tried with just table name parameter (excerpt from another post on this website) :
CREATE OR REPLACE FUNCTION test(_tbl regclass, OUT result integer) AS
$func$
BEGIN
EXECUTE format('SELECT (EXISTS (SELECT FROM %s))::int', _tbl)
INTO result;
END
$func$ LANGUAGE plpgsql;
and called with SELECT test('"vDxi"'); but the result is :
ERROR: syntax error at or near "FROM"
LINE 1: SELECT (EXISTS (SELECT FROM "vDxi"))::int
^
QUERY: SELECT (EXISTS (SELECT FROM "vDxi"))::int
CONTEXT: PL/pgSQL function test(regclass) line 3 at EXECUTE statement
SQL state: 42601
Since I'm a real newbie in PLSQL, I don't know where the error is (tried a SELECT * ... with no success).
And the calling query does not permit me to select column names, if I can make it working...

Creating a trigger function in PostgreSQL

I'm creating a trigger function that must populate a field called "numero_cip". This field must be fill just one time after a "INSERT ROW", because this field is a join from: "BR" + ID FIELD + SUFIXO FIELD.
So, i'm trying to create this trigger function:
CREATE OR REPLACE FUNCTION numeradora_cip()
RETURNS trigger AS $$
DECLARE
sufixo varchar(2);
numero_cip varchar(60);
BEGIN
sufixo := select p.sufixo from produto p where p.id = NEW.id_produto;
NEW.numero_cip = select 'BR' || lpad(NEW.id, 11, '0') || sufixo;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
But i got the error:
ERROR: syntax error at or near "select"
LINE 7: sufixo := select p.sufixo from produto p where p.id = NE...
PS: This is my first time creating a trigger function.
From the fine manual:
40.5.3. Executing a Query with a Single-row Result
The result of a SQL command yielding a single row (possibly of multiple columns) can be assigned to a record variable, row-type variable, or list of scalar variables. This is done by writing the base SQL command and adding an INTO clause. For example,
SELECT select_expressions INTO [STRICT] target FROM ...;
...
So you're looking for:
select p.sufixo into sufixo from produto p where p.id = NEW.id_produto;
And then, since your PL/pgSQL, you can do a simple string concatenation to get your numero_cip:
NEW.numero_cip := 'BR' || lpad(NEW.id, 11, '0') || sufixo
CREATE OR REPLACE FUNCTION numeradora_cip()
RETURNS trigger AS $$
DECLARE
sufixo varchar(2);
numero_cip varchar(60);
BEGIN
select p.sufixo into sufixo from produto p where p.id = NEW.id_produto;
NEW.numero_cip := select 'BR' || lpad(NEW.id, 11, '0') || sufixo;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';

pgsql sql functions sequential execution

If I have these two Postgres function definitions saved in two seperate .sql files:
CREATE OR REPLACE FUNCTION column_exists(tablename text, colname text) RETURNS boolean AS
$BODY$
DECLARE
q text;
field_name text;
onerow record;
BEGIN
q = 'SELECT column_name FROM information_schema.columns WHERE table_name='''||tablename||''' AND table_schema =''public''';
FOR onerow IN EXECUTE q
LOOP
field_name := onerow.column_name;
IF ((field_name = colname)) then
RETURN true;
END IF;
END LOOP;
RETURN false;
END;
$BODY$
LANGUAGE plpgsql
CREATE OR REPLACE FUNCTION correct_col_names() RETURNS VOID AS
$BODY$
DECLARE
q boolean;
BEGIN
-- rename name column to Name
select column_exists('National_Parks', 'name') as q;
IF q = TRUE THEN
alter table "National_Parks"
rename column name to "Name";
END IF;
-- remance descriptio column to description
select column_exists('National_Parks', 'descriptio') as q;
IF q = TRUE THEN
alter table "Natioanl_Parks"
rename column descriptio to "Description";
END IF;
END
$BODY$
LANGUAGE plpgsql
What is the syntax I need to use to call the sequentially, say in another script? I tried
select correct_col_names()
and this returns the following error:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function "correct_col_names" line 7 at SQL statement
********** Error **********
ERROR: query has no destination for result data
SQL state: 42601
Hint: If you want to discard the results of a SELECT, use PERFORM instead.
Context: PL/pgSQL function "correct_col_names" line 7 at SQL statement
TIA.
The problem is that you have SELECT statements that aren't doing anything with the data. Your
select column_exists('National_Parks', 'name') as q;
should be
select column_exists('National_Parks', 'name') INTO q;
The as simply aliases the result as "q" for that query, it doesn't actually put it into the q variable.
Your syntax for calling the functions (select correct_col_names()) is correct for SQL. Once you fix the two errors in that function, it should work.
However, if you were to try select correct_col_names() inside another PL/PGSQL function, you would get the same error, because the select statement isn't actually doing anything with the results. perform correct_col_names() would run without error, because PERFORM is PL/PGSQL syntax for calling something when you don't want to save the result.