Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1svDYn-00DFUt-3M for pgsql-general@arkaria.postgresql.org; Mon, 30 Sep 2024 10:23:21 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1svDYl-00G2wC-O7 for pgsql-general@arkaria.postgresql.org; Mon, 30 Sep 2024 10:23:19 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1svDYl-00G2w0-AL for pgsql-general@lists.postgresql.org; Mon, 30 Sep 2024 10:23:19 +0000 Received: from mail-yw1-x1129.google.com ([2607:f8b0:4864:20::1129]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1svDYh-001p4U-AZ for pgsql-general@lists.postgresql.org; Mon, 30 Sep 2024 10:23:18 +0000 Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-6da395fb97aso30227007b3.0 for ; Mon, 30 Sep 2024 03:23:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727691795; x=1728296595; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=j4CDWFEzrN3G7WndJFuabxEXVsReIS5EmRuIEW/hv4c=; b=i75NpNv7EDOYZUa637JLWE2tmvo2sDT3/nas0sME4gQIU2DnRKCE14XCakTz1SwD++ Cj1z72q75no0Pk41Gq0K8k0Z5mEhctECTwrpb4eEiFGCMNPGHx4ZMtNj7boKqSIf/KN1 4t+rbX2Sg5KS4s3SmD1GHnLig421e/V0Si3T21hJTGM2y/OwvlH6D1FYHmByRDel8Bgz Sfaw3Vi48c0BJ4yOikqvZHD55hNFfXpQrntAejQdWO9m/jvBSyTrAg2gI+6IKdYU+3wU Y6QuQqpUbzD+o0xdoadlOLP5/K0hliYUHL9F4OSRqOW1Xamdvh0bSgbTMbAwpMi48R4/ SeNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727691795; x=1728296595; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=j4CDWFEzrN3G7WndJFuabxEXVsReIS5EmRuIEW/hv4c=; b=EraWm/gLop9lY902wOsx/10bTIQ2TI+fau+bp4FUEiqTP5tNtD8+Q6i+HAypHg6T+S DK7TeRBOw6D47EluHrcKcDSQIqaeCSqd/725PWSbUULBzlE0/F7aLHpCDgCnAlWYoirh ZT/ksTaPCf7C2s1Bk5d9Dy6h0UWGovqd0H7mU2n3plKCZA+iPEYJMwjy0R3joFtyedNT ZjJkRArZQNk8OhBp/5Jh8vt6odQRDnZ8XGhaBN2l62VQ8wsC0f5awnHXXpTqA6c0hvAU BusBhd5yBTEhrsLlr4WwYBYXb52zBPuVMmgJNC8y1mEzgWKC0OAyUyLDhYx/A1tCrwmz g9oQ== X-Gm-Message-State: AOJu0YxllyW8X9LC0zK4IneOCPhflogGPvZWphRJk/TD4ap80Fgm2Mxw g2je8US8I1bFHw/Fln7uBt1zbAnUQKPbxrHJihut3X3/LRUOcKX0r+f5IrblO4phhRlheVTo2p/ +GYKaBGUUqFQJU/SBaXZv/OvcSlHL/YCEd1g= X-Google-Smtp-Source: AGHT+IFYarCzZUz3mwmQNl4CuLyZBynTT+t9lYh23+MXVV26ZnXl12hS/knr4ambdengfm1hurG09QQuL+7CMKRFpVE= X-Received: by 2002:a05:690c:4289:b0:6dd:eb45:cf11 with SMTP id 00721157ae682-6e2475faa25mr62286297b3.43.1727691795018; Mon, 30 Sep 2024 03:23:15 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Pavel Stehule Date: Mon, 30 Sep 2024 12:22:38 +0200 Message-ID: Subject: Re: Trouble in generating the plpgsql procedure code To: Nikhil Ingale Cc: pgsql-general@lists.postgresql.org Content-Type: multipart/alternative; boundary="000000000000b93b59062353973c" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000b93b59062353973c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi use format function do $$ begin for i in 1..10 loop execute format($_$ create or replace function %I(a int) returns int as $__$ begin return a + %s; end; $__$ language plpgsql; $_$, 'foo_' || i, i); end loop; end; $$; DO (2024-09-30 12:21:29) postgres=3D# \sf foo_1 CREATE OR REPLACE FUNCTION public.foo_1(a integer) RETURNS integer LANGUAGE plpgsql AS $function$ begin return a + 1; end; $function$ Regards Pavel po 30. 9. 2024 v 12:09 odes=C3=ADlatel Nikhil Ingale n= apsal: > Guys, > I have a requirement to generate the plpgsql procedure code itself by > reading the postgresql metadata or system tables. I don't want to write a > plpgsql procedure every time for every table because I have many tables i= n > db. I want to generate the procedure for more than 100 tables and write a= ll > the procedure code to a single file which can be used to execute to creat= e > the actual procedure. > > While I generate the procedure code I want the code to be added to the > next line in a better readability format. I'm writing the generated code > for all tables in single shot with the help of COPY to PROG > > My procedure code is mentioned below. But the generated code is having \n > instead of adding the code to the next line. > > > CREATE OR REPLACE FUNCTION emp_dts_iot () RETURNS TRIGGER AS > $BODY$\nDECLARE\n nCount INT;\nBEGIN\n IF TG_OP IN ('INSERT') THEN\n > SELECT count(1) INTO nCount FROM employee \n WHERE id= =3D > :NEW.id AND STATUS_FLAG =3D 9 ; \n IF COALESCE(nCount,0) > 0 > THEN\n UPDATE test.employee \n id =3D > :NEW.\n ,description =3D :NEW.description\n > ,state_flag =3D 2\n WHERE id =3D :NEW.id ; \n > ELSE\n\t INSERT INTO employee VALUES ( \n > :NEW.id\n ,:NEW.description\n ,1 ) ; \n > END IF;\n\n ELSIF TG_OP IN ('UPDATE') THEN\n SELECT count(1) > INTO nCount FROM test.employee\n > > The code should have been written in the next line instead of \n. > > > drop procedure insteadoftriggers; > create or replace procedure insteadoftriggers( IN e_owner TEXT, > p_table_name TEXT DEFAULT NULL, emp_owner TEXT DEFAULT 'test') > AS $$ > DECLARE > TstTableCursor CURSOR IS SELECT table_name,test_table_name FROM > app_tables WHERE TEST_TABLE_NAME IS NOT NULL AND table_name =3D > COALESCE(p_table_name,table_name) AND owner=3D COALESCE(e_owner,owner) ; > > l_cnt NUMERIC :=3D 0; > tab TEXT :=3D E'\t'; > l_col_str TEXT; > l_table_Name TEXT ; > cKeyCol TEXT DEFAULT '' ; > cWhere TEXT DEFAULT '' ; > trigger_body TEXT ; > cSpace character varying(100) :=3D ' '; > BEGIN > FOR TstTableRec IN TstTableCursor > LOOP > l_table_name :=3D TstTableRec.TABLE_NAME ; > trigger_body :=3D > 'CREATE OR REPLACE FUNCTION prod.' || TstTableRec.TABLE_NAME || '_IOT() > RETURNS TRIGGER AS $BODY$' || CHR(10) || > 'DECLARE' || CHR(10) || > ' ' || 'nCount INT;' || chr(10) || > 'BEGIN' || chr(10) || > ' ' || 'IF TG_OP IN ' || '(' ||'''''INSERT'''''||') THEN' || chr(10) || > ' SELECT count(1) INTO nCount FROM test.' || > TstTableRec.TABLE_NAME || chr(10) || > GetTrigClause(p_tdaowner, lower(TstTableRec.TABLE_NAME), > ':NEW.') || ' AND STATUS_FLAG =3D 9 ; ' || chr(10) || > > ' '|| 'IF COALESCE(nCount,0) > 0 THEN' || chr(10) |= | > > Can someone help me here? > > Regards, > Nikhil Ingale > --000000000000b93b59062353973c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi

use format function
=

do $$
begin=C2=A0 for i in 1..10
=C2=A0 loop
=C2=A0 =C2=A0 execute format($_$create or replace function %I(a int)
returns int as $__$
begin
= =C2=A0 return a + %s;
end;
$__$ language plpgsql;
$_$, 'foo_&#= 39; || i, i);
=C2=A0= end loop;
end;
$$;
DO

(20= 24-09-30 12:21:29) postgres=3D# \sf foo_1
CREATE OR REPLACE FUNCTION pub= lic.foo_1(a integer)
=C2=A0RETURNS integer
=C2=A0LANGUAGE plpgsql
= AS $function$
begin
=C2=A0 return a + 1;
end;
$function$
=

Regards

Pavel
<= /div>
p= o 30. 9. 2024 v=C2=A012:09 odes=C3=ADlatel Nikhil Ingale <niks.bgm@gmail.com> napsal:
Guys,
I hav= e a requirement to generate the plpgsql procedure code itself by reading th= e postgresql metadata or system tables. I don't want to write a plpgsql= procedure every time for every table because I have many tables in db. I w= ant to generate the procedure for more than 100 tables and write all the pr= ocedure code to a single file which can be used to execute to create the ac= tual procedure.

While I generate the procedure code I want the code = to be added to the next line in a better readability format. I'm writin= g the generated code for all tables in single shot with the help of COPY to= PROG

My procedure code is mentioned below. But th= e generated code is having \n instead of adding the code to the next line.<= /div>


CREATE OR REPLACE FUNCTION emp_dts_= iot () RETURNS TRIGGER AS $BODY$\nDECLARE\n =C2=A0nCount INT;\nBEGIN\n =C2= =A0 IF TG_OP IN ('INSERT') THEN\n =C2=A0 =C2=A0 =C2=A0 =C2=A0 SELEC= T count(1) INTO nCount FROM employee \n =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 WHERE id =3D :NEW.id AND STATUS_FLAG =3D 9 ; \n =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IF COALESCE(nCount,0) > 0 THEN= \n =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UPDATE test.empl= oyee=C2=A0 \n=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 id =3D :NEW.\n =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 ,description =3D :NEW.description\n =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ,state_flag =3D 2\n =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 WHERE id =3D :NEW.id ; \n =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ELSE\n\t =C2=A0 =C2=A0 =C2=A0 =C2=A0 INS= ERT INTO employee VALUES ( \n =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 :NEW.id\n =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 ,:NEW.description\n=C2=A0 =C2=A0 ,1 ) ; \n =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0END IF;\n\n =C2=A0 ELSIF TG_OP IN ('U= PDATE') THEN\n =C2=A0 =C2=A0 =C2=A0 =C2=A0 SELECT count(1) INTO nCount = FROM test.employee\n=C2=A0 =C2=A0=C2=A0

The co= de should have been written in the next line instead of \n.

<= /div>

drop procedure insteadoftriggers;
create or replace proced= ure insteadoftriggers( IN e_owner TEXT, p_table_name TEXT DEFAULT NULL, emp= _owner TEXT DEFAULT 'test')
AS $$
DECLARE
=C2=A0 =C2=A0 Ts= tTableCursor CURSOR IS SELECT table_name,test_table_name FROM app_tables WH= ERE TEST_TABLE_NAME IS NOT NULL AND table_name =3D COALESCE(p_table_name,ta= ble_name) AND owner=3D COALESCE(e_owner,owner) ;
=C2=A0 =C2=A0
l_cnt NUMERIC :=3D 0;
=C2=A0 =C2=A0 tab TEXT :=3D E'\t';
=C2= =A0 =C2=A0 l_col_str TEXT;
=C2=A0 =C2=A0 l_table_Name TEXT ;
=C2=A0 = =C2=A0 cKeyCol TEXT DEFAULT '' ;
=C2=A0 =C2=A0 cWhere TEXT DEFAU= LT '' ;
=C2=A0 =C2=A0 trigger_body TEXT ;
=C2=A0 =C2=A0 cSpac= e character varying(100) :=3D ' =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 '= ;;
BEGIN
=C2=A0 =C2=A0 FOR TstTableRec IN TstTableCursor
=C2=A0 = =C2=A0 LOOP
=C2=A0 =C2=A0 =C2=A0 =C2=A0 l_table_name :=3D TstTableRec.TA= BLE_NAME ;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 trigger_body :=3D
'CREATE = OR REPLACE FUNCTION prod.' || TstTableRec.TABLE_NAME || '_IOT() RET= URNS TRIGGER AS $BODY$' || CHR(10) ||
'DECLARE' || CHR(10) |= |
' =C2=A0' || 'nCount INT;' || chr(10) ||
'BEGIN= ' || chr(10) ||
' =C2=A0 ' || 'IF TG_OP IN ' || '= ;(' ||'''''INSERT'''''||') = THEN' || chr(10) ||
' =C2=A0 =C2=A0 =C2=A0 =C2=A0 SELECT count(1= ) INTO nCount FROM test.' || TstTableRec.TABLE_NAME || chr(10) ||
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 GetTrigClause(p_tdaowner, lower(TstTable= Rec.TABLE_NAME), ':NEW.') || ' AND STATUS_FLAG =3D 9 ; ' ||= chr(10) ||

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0' =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0'|| 'IF COALESCE(nCount,0) > 0= THEN' || chr(10) ||

Can someone help me here?

Regards,
Nikhil Ingale
--000000000000b93b59062353973c--