How do I declare and run an anonymous plpgsql block in liquibase - plpgsql

I am running liquibase changelog with changeset definition and anonymous plpgsql block as described below , while executing i get sql syntax exception .I am not able to find the correct syntax to use for this.
Database changelog :
<changeSet author="wamk" id="20210909102601">
<preConditions onFail="MARK_RAN">
<dbms type="postgresql" />
</preConditions>
<sqlFile path="027-rename-psps.sql" relativeToChangelogFile="true" endDelimiter="/" dbms="PostgreSQL" encoding="utf8" splitStatements="true"/>
</changeSet>
</databaseChangeLog>
'027-rename-psps.sql' file contents :
declare
cur_rename cursor (modulekeyold varchar) for
select * from payment_module_config where module_key = modulekeyold;
counter integer = 0;
commitnum integer = 100;
begin
FOR recordvar IN cur_rename('WirecardPaymentService_1.0') loop
raise notice 'Value: %', recordvar;
UPDATE payment_module_config SET module_key='GetNet V1' WHERE id = recordvar.id;
counter = counter + 1;
if(counter%commitnum=0) then
raise notice '>>> counter: %', counter;
commit;
end if;
end loop;
commit;
end;
/
EXCEPTION :
12:26:23.933 [main] ERROR liquibase.changelog.ChangeSet - Change Set db/changelog/027-rename-psps.sql::raw::includeAll failed. Error: Syntax error in SQL statement "DECLARE
CUR_RENAME[*] CURSOR (MODULEKEYOLD VARCHAR) FOR
SELECT * FROM PAYMENT_MODULE_CONFIG WHERE MODULE_KEY = MODULEKEYOLD;
COUNTER INTEGER = 0;
COMMITNUM INTEGER = 100;
BEGIN ...

Related

debugging psql - session procedure

I am trying to modify an existing sessions procedure to add cycle count.The error I am getting is
SQL Error [42601]: ERROR: syntax error at or near "END"
Position: 3587
--call transactions_packs.tep_session()
CREATE OR REPLACE PROCEDURE transactions_packs.tep_session()
LANGUAGE plpgsql
AS $procedure$
DECLARE
session "transactions_packs"."simple_sessions";
"session_toSearch" TEXT;
"end_timestamp" TIMESTAMP WITH TIME ZONE;
"energy" NUMERIC;
"charge" NUMERIC;
"duration" NUMERIC;
"cycle_count" numeric;
"f" record ;
BEGIN
cycle_count = '0';
-- go to statement fore session reset
FOR session IN SELECT * FROM "transactions_packs"."simple_sessions" WHERE "sessionDuration" IS NULL
LOOP
BEGIN
IF session."sessionType" = 0 THEN
"session_toSearch" := 'Charging';
ELSIF session."sessionType" = 1 THEN
"session_toSearch" := 'Discharging';
END IF;
-- Session_count:Start
EXECUTE FORMAT('
FOR f IN select (current' || '%s' || '), "timestamp"
FROM "transactions_packs"."basic_measurements_packs" a order by a."timestamp" desc
LOOP
BEGIN
IF AVG((current' || '%s' || '))
OVER (ORDER BY "f"."timestamp" ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) > 0.01
then cycle_count = cycle_count + 1;
END IF;
END
END LOOP;',"session_toSearch","session_toSearch")
-- get value from If and else statement to fetch records from charging and discharging col
--Session_count :End
END ;
END LOOP;
end;
$procedure$
;
where -
schema is transactions_packs
tables are -
simple_sessions
basic_measurements_packs
Please let me know if there is any part of query is which cannot be understood.
The variable "hell" sounds like useless here, try something like this :
create or replace procedure "public"."extract"(arg json)
language plpgsql as $$
begin
raise notice 'test:%', arg->'global'->>'packetType';
raise notice 'test1:%', arg-> 'transactional'->>'A';
-- freeze the input
end ;
$$;

PostgreSql procedure structure

I have a syntax error on a procedure (PostgreSQL) and I can't find the mistake. I need a procedure with the variable declaration, a for loop, and a transaction.
Here is a sample of the structure I'm using.
CREATE OR REPLACE PROCEDURE repor_dados()
LANGUAGE plpgsql AS
$$
DECLARE
utilizador int;
data_acesso date;
r record;
BEGIN
BEGIN -- begin transaction
select 2 ,4 into data_acesso,utilizador;
IF EXISTS(select 2) then -- condition
BEGIN
-- for each select result
FOR r IN SELECT 1,2,3
LOOP
-- do something
IF r = 1 THEN
SELECT 3;
ELSE
SELECT 4;
END IF;
END LOOP;
END;
COMMIT; -- commit transaction
END
$$
I am working with PostgreSQL 13.2.
The error is:
ERROR: syntax error at end of input LINE 30: $$

Postgresql dynamic sql syntax error

I have a function that accepts an array of table names and loops through the array to create a trigger for each table. The function compiles and is created with no errors.
When I go try to run the function I keep getting the following error and I am not sure what's wrong with my syntax
ERROR:
ERROR: unterminated quoted string at or near "';
ELSE
RAISE EXCEPTION ''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %, %'',TG_OP, TG_LEVEL;
RETURN NULL;
END IF;
INSERT INTO audit.Organization VALUES (audit_row.*);
RETURN null;
END;
"
LINE 53: audit_row.statement_only = 't';
^
USAGE:
SELECT audit.temp_create_trigger(ARRAY['Organization'])
Here's the function:
CREATE OR REPLACE FUNCTION audit.temp_create_trigger(table_names character varying[])
RETURNS character varying AS
$BODY$
DECLARE
table_name varchar;
i int;
BEGIN
FOR i in 1..array_upper(table_names, 1) LOOP
EXECUTE format('CREATE OR REPLACE FUNCTION audit.trigger_function_%1$s() RETURNS TRIGGER AS $$
DECLARE
audit_row audit.%1$s;
include_values boolean;
log_diffs boolean;
h_old hstore;
h_new hstore;
excluded_cols text[] = ARRAY[]::text[];
BEGIN
IF TG_WHEN <> ''AFTER'' THEN
RAISE EXCEPTION ''audit.trigger_function_%1$s may only run as an AFTER trigger'';
END IF;
audit_row = ROW(
nextval(''audit.%1$s_event_id_seq''), -- event_id
TG_TABLE_SCHEMA::text, -- schema_name
TG_TABLE_NAME::text, -- table_name
TG_RELID, -- relation OID for much quicker searches
session_user::text, -- session_user_name
current_timestamp, -- action_tstamp_tx
statement_timestamp(), -- action_tstamp_stm
clock_timestamp(), -- action_tstamp_clk
txid_current(), -- transaction ID
current_setting(''application_name''), -- client application
inet_client_addr(), -- client_addr
inet_client_port(), -- client_port
current_query(), -- top-level query or queries (if multistatement) from client
substring(TG_OP,1,1), -- action
NULL, NULL, -- row_data, changed_fields
''f'' -- statement_only
);
IF NOT TG_ARGV[0]::boolean IS DISTINCT FROM ''f''::boolean THEN
audit_row.client_query = NULL;
END IF;
IF TG_ARGV[1] IS NOT NULL THEN
excluded_cols = TG_ARGV[1]::text[];
END IF;
IF (TG_OP = ''UPDATE'' AND TG_LEVEL = ''ROW'') THEN
audit_row.row_data = hstore(OLD.*) - excluded_cols;
audit_row.changed_fields = (hstore(NEW.*) - audit_row.row_data) - excluded_cols;
IF audit_row.changed_fields = hstore('') THEN
-- All changed fields are ignored. Skip this update.
RETURN NULL;
END IF;
ELSIF (TG_OP = ''DELETE'' AND TG_LEVEL = ''ROW'') THEN
audit_row.row_data = hstore(OLD.*) - excluded_cols;
ELSIF (TG_OP = ''INSERT'' AND TG_LEVEL = ''ROW'') THEN
audit_row.row_data = hstore(NEW.*) - excluded_cols;
ELSIF (TG_LEVEL = ''STATEMENT'' AND TG_OP IN (''INSERT'',''UPDATE'',''DELETE'',''TRUNCATE'')) THEN
audit_row.statement_only = ''t'';
ELSE
RAISE EXCEPTION ''''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'''',TG_OP, TG_LEVEL;
RETURN NULL;
END IF;
INSERT INTO audit.%1$s VALUES (audit_row.*);
RETURN null;
END;
$$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION audit.trigger_function_%1$s()
OWNER TO postgres;', table_names[i]);
EXECUTE format('CREATE TRIGGER audit.%1$s_trigg
BEFORE INSERT OR UPDATE
ON audit.%1$s
FOR EACH ROW
EXECUTE PROCEDURE audit.trigger_function_%1$s();', table_names[i]);
END LOOP;
RETURN 'SUCCESS';
END;
$BODY$
LANGUAGE plpgsql
COST 100;
ALTER FUNCTION audit.temp_create_trigger(character varying[])
OWNER TO postgres;
There are missing and superfluous quotes :
--IF audit_row.changed_fields = hstore('') THEN -- missing quotes
IF audit_row.changed_fields = hstore('''') THEN
.....
--RAISE EXCEPTION ''''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'''',TG_OP, TG_LEVEL; --more quotes then needed
RAISE EXCEPTION ''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'',TG_OP, TG_LEVEL;

Creating TEMP TABLE dynamically in Postgresql and selecting the same table in FOR loop. But getting the error near PIPE symbol

do
$xyz$
declare
y text;
i record;
begin
y := to_char(current_timestamp, 'YYYYMMDDHHMMSS');
raise notice '%',y;
execute 'CREATE TEMP TABLE someNewTable'
||y
||' AS select * from ( VALUES(0::int,-99999::numeric), (1::int, 100::numeric)) as t (key, value)';
for i in (select * from someNewTable||y) loop
raise notice '%',i.key;
end loop;
end;
$xyz$ language 'plpgsql'
ERROR: syntax error at or near "||"
LINE 13: for i in (select * from someNewTable||y) loop
Im unable to understand why the error is at the PIPE symbol. Please help me. I have been trying in Oracle db too, but same error. Am I doing anything wrong here?
The query in for ... loop statement also has to be dynamic, so you should use execute twice.
Use the format() function which is very convenient in conjunction with execute:
do $xyz$
declare
y text;
i record;
begin
y := to_char(current_timestamp, 'YYYYMMDDHHMMSS');
raise notice '%', y;
execute format($ex$
create temp table somenewtable%s
as select * from (
values
(0::int, -99999::numeric),
(1::int, 100::numeric)
) as t (key, value)
$ex$, y);
for i in
execute format($ex$
select * from somenewtable%s
$ex$, y)
loop
raise notice '%',i.key;
end loop;
end;
$xyz$ language 'plpgsql';

Run DELETE query in trigger function

I'm trying to run a DELETE and UPDATE query inside a trigger function in PL/pgSQL.
CREATE OR REPLACE FUNCTION trg_delete_order_layer()
RETURNS trigger AS
$BODY$
DECLARE index_ INTEGER;
DECLARE a RECORD;
BEGIN
IF EXISTS (SELECT * FROM map_layers_order WHERE id_map = OLD.id_map)
THEN index_ := position FROM map_layers_order WHERE id_map = OLD.id_map AND id_layer = OLD.id_layer AND layer_type = 'layer';
ELSE index_ := 0;
END IF;
RAISE NOTICE 'max_index % % %', index_, OLD.id_map, OLD.id_layer;
EXECUTE 'DELETE FROM map_layers_order WHERE id_map = $1 AND id_layer = $2 AND layer_type = $3' USING OLD.id_map, OLD.id_layer, 'layer';
EXECUTE 'UPDATE map_layers_order SET position = position -1 WHERE id_map = $1 AND position > $2' USING OLD.id_map, index_;
VALUES (OLD.id_map, OLD.id_layer, 'layer', index_);
RETURN OLD;
END;
$BODY$
LANGUAGE plpgsql;
I don't know why i'm getting this error in the line where it runs the DELETE query:
Query has no destination for result data
Why is this error happen and how can I solve this?
Obviously if I use EXECUTE...INTO, I get a more reasonable error saying that the query has no result.