Files
PgTidy/testdata/corpus/test_mm_proc.pgsql
T
warkanum f17e87e749
CI / Test (push) Failing after 24s
CI / Build (push) Has been skipped
fix(body): prevent joining continuation lines to comments
* Ensure comment-only lines are flushed before adding new statements
* Adjust logic to handle col-0 continuation lines correctly
2026-06-30 22:51:25 +02:00

1571 lines
55 KiB
PL/PgSQL

CREATE OR REPLACE FUNCTION mm_proc(
p_doctype text --File Types: html, docx, text, allfieldvalues
,p_commtype text --Merge Data Type: e.g. SMS,Email,All (Will be passed through to menu/taglist funct)
,p_template bytea --Source/Template file to be merge
,p_data_prefix text --Table prefix for data source. e.g. tcli (client) , sta (standard letters)
,p_data_rid integer --rid for given table prefix
,p_filterdata json = NULL --Advanced filter data.
,OUT p_doc bytea --Merged document output
,OUT p_docguid text --optional guid to store document guid from tempfile table. (For disk reading)
,OUT p_retval integer
,OUT p_errmsg text
)
LANGUAGE plpgsql
VOLATILE
AS
$$
DECLARE
--Error Handling--
m_funcname text = 'mm_proc';
m_errmsg text;
m_errcontext text;
m_errdetail text;
m_errhint text;
m_errstate text;
m_retval integer;
--Error Handling--
m_blankexec text;
m_comma text;
m_debug_exestr text;
m_exec_orderstr text;
m_execfilter text;
m_execstr text;
m_fields json;
m_guid citext;
m_json json;
m_json_full json;
m_json_full_complex jsonb;
m_result text;
m_tablefilter text;
m_temppath citext;
m_user citext;
m_exttype citext;
m_returnvalues boolean = false;
m_data_prefix citext;
m_data_rid integer;
m_rid_comm integer;
m_rid_commattachment integer;
m_rid_obl integer;
m_doctype citext;
m_ltime timestamp;
m_hasfilestream boolean;
m_rid_obligation integer;
g_debug boolean;
g_tag_s text;
g_tag_e text;
g_tag_split text;
g_tag_oper text;
g_mtype_root integer = 0;
g_mtype_field integer = 1;
g_mtype_tblfield integer = 2;
g_mtype_tblroot integer = 3;
g_mtype_aggfield integer = 4;
g_mtype_picture integer = 5;
g_mtype_special integer = 6;
g_mtype_filter integer = 7;
g_mtype_condfield integer = 8;
g_mtype_docreplace integer = 9;
g_mtype_html integer = 10;
g_benchmark integer;
a_tblroot integer[];
a_types citext[];
a_inner_selected citext[];
r_template record;
r_doc record;
r_lp record;
r_lp_t record;
r_lp_c record;
r_retval record;
r_tmp record;
--r_lp_prev record;
m_start timestamp = clock_timestamp();
BEGIN
p_retval = 0;
p_errmsg = '';
G_DEBUG = True;
G_BENCHMARK = 0;
G_TAG_S = '[*'; --chr(171);
G_TAG_E = '*]';--chr(187);
G_TAG_SPLIT = '|';
G_TAG_OPER = ':'; --operator
m_exttype = 'txt';
a_types = array['html','docx','txt','plainhtml','allfieldvalues']; --
m_hasfilestream = false;
a_inner_selected = array[]::citext[];
m_ltime = clock_timestamp();
m_guid = newid();
m_user = f_getuser();
-- if p_doctype ilike '%plain%' and f_iscompressed(p_template) in ('none')
-- and byteatotext(p_template) not ilike '%'|| G_TAG_S || '%' || G_TAG_E || '%'
-- then
-- raise warning 'No tags to merge in plain template.';
-- p_doc = p_template;
-- return;
-- end if;
-- perform log_event(m_funcname,format('INIT _ type=%s commtype=%s p_data_prefix=%s p_data_rid=%s Template:%s'
-- ,p_doctype, p_commtype,p_data_prefix,p_data_rid
-- ,case when octet_length(p_template) < 100 then byteatotext(p_template) else octet_length(p_template)::text end
-- ),bt_enum('eventlog','local notice'));
if p_data_prefix::citext = 'com'
then
select c.rid_communication
, c.rid_parent
, c.tableprefix
from communication c
where c.rid_communication = p_data_rid into m_rid_comm, m_data_rid, m_data_prefix;
elsif p_data_prefix::citext = 'cra'
then
m_rid_commattachment = p_data_rid;
select c.rid_communication
, c.rid_parent
, c.tableprefix
, ca.rid_obligation
, dt.typex
from commattachment ca
inner join communication c on c.rid_communication = ca.rid_parent
and ca.tableprefix = 'com'
left outer join document d on d.rid_document = ca.rid_document
left outer join documenttype dt on dt.rid_documenttype = d.rid_documenttype
where ca.rid_commattachment = p_data_rid into m_rid_comm, m_data_rid, m_data_prefix, m_rid_obl, m_doctype;
elsif p_data_prefix::citext = 'ctl'
then
select ctl.rid_parent as rid_parent
, ctl.tableprefix as parent_prefix
from tasklist ctl --inner join t_adproclient cli on cli.rid_adproclient = ctl.rid_parent -- and ctl.tableprefix = 'tcli'
where ctl.rid_tasklist = p_data_rid into m_data_rid, m_data_prefix;
elsif p_data_prefix::citext = 'ehr'
then
raise exception 'Merging email headers are not supported at this time.';
else
m_data_prefix = p_data_prefix;
m_data_rid = p_data_rid;
end if;
---init: start---
select format('tmpl_%s_%s_%s.%s', m_data_prefix, m_data_rid, m_guid, p_doctype)::citext as filename
,''::citext as filepath
,''::citext as debugsql_filename
,''::citext as debug_filename
,''::citext as debug_peekfilename
,''::citext as magictype
,'T' || m_guid::citext as guid
,p_template::bytea as blob
into r_template;
select format('doc_%s_%s_%s.%s', m_data_prefix, m_data_rid, m_guid, p_doctype)::citext as filename
,''::citext as filepath
,'D' || m_guid::citext as guid
,null::bytea as blob
into r_doc;
-- perform log_event(m_funcname,format('init = p_doctype = %s p_data_prefix = %s p_data_rid = %s p_template[size] = %s'
-- ,p_doctype,p_data_prefix,p_data_rid,octet_length(p_template)),bt_enum('eventlog','local notice'));
if p_doctype = 'allfieldvalues'
then
m_returnvalues = true;
elsif p_doctype::citext <> all(a_types)
then
raise exception 'This type [%] is not yet supported. Allowed types: %', p_doctype, a_types;
end if;
if p_template is null and not m_returnvalues
then
p_retval = 1;
p_errmsg = 'No template';
return;
end if;
if p_commtype ilike '%sms%' and (p_doctype ilike '%text%' or p_doctype ilike '%html%' or p_doctype ilike '%all%')
then
p_doctype = 'plainhtml';
end if;
select f_normpath(b.programpath || '/temp/mailmerge')::citext
,b.sqldebuglevel > 99
from f_bus() b limit 1
into m_temppath, G_DEBUG;
if m_hasfilestream or G_DEBUG
then
perform pl_mkdir(m_temppath);
end if;
r_template.magictype = f_normpath(f_iscompressed(p_template))::citext;
r_template.filepath = f_normpath(format('%s/%s',m_temppath, r_template.filename))::citext;
r_template.debugsql_filename = f_normpath(format('%s/%s%s/%s.pgsql',m_temppath, p_data_prefix, p_data_rid, r_template.filename))::citext;
r_template.debug_filename = f_normpath(format('%s/%s%s/%s.debug.json',m_temppath, p_data_prefix, p_data_rid, r_template.filename))::citext;
r_template.debug_peekfilename = f_normpath(format('%s/%s%s/%s.peek.json',m_temppath, p_data_prefix, p_data_rid, r_template.filename))::citext;
if g_debug
then
perform pl_mkdir(f_normpath(format('%s/%s%s',m_temppath, p_data_prefix, p_data_rid)));
perform pl_writefile(f_normpath(format('%s/%s%s/%s.template.docx',m_temppath, p_data_prefix, p_data_rid,r_template.filename))
,p_template);
end if;
r_doc.filepath = f_normpath(format('%s/%s',m_temppath, r_doc.filename))::citext;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Before MergeMenu SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
drop table if exists tmp_merge_init_src;
create temp table tmp_merge_init_src
--on commit drop
as
with msrc as (
select *
from crm_get_merge_menu(p_commtype::citext) p
), src as (
select c.rid_tree_mergefeld::integer as rid
,nv(c.rid_parent)::integer as rid_parent
,btrim(nv(c.mergetag),' ')::citext as mergetag
,nv(c.mergetype) as merge_type
,btrim(nv(c.tablename),' ')::citext as table_name
,btrim(nv(c.fieldname),' ')::citext as field_name
,btrim(nv(c.filterstring),' ')::citext as filter_string
,btrim(nv(g.orderstring),' ')::citext as order_string
--parent
,nv(p.rid_tree_mergefeld)::integer as parent_rid
,nv(p.rid_parent)::integer as parent_rid_parent
,btrim(p.mergetag,' ')::citext as parent_mergetag
,nv(p.mergetype)::integer as parent_merge_type
,ifblnk(btrim(p.tablename,' '), btrim(nv(g.tablename),' '))::citext as parent_table_name
,btrim(nv(p.fieldname),' ')::citext as parent_field_name
,ifblnk(btrim(p.filterstring,' '),btrim(nv(g.filterstring),' '))::citext as parent_filter_string
,ifblnk(btrim(p.orderstring,' '),btrim(nv(g.orderstring),' '))::citext as parent_order_string
--grand parent
,nv(g.rid_tree_mergefeld)::integer as grand_rid
,btrim(g.mergetag,' ')::citext as grand_mergetag
,nv(g.mergetype)::integer as grand_merge_type
,ifblnk(g.tablename, nv(g.tablename))::citext as grand_table_name
,btrim(nv(g.fieldname),' ')::citext as grand_field_name
,btrim(nv(g.filterstring),' ')::citext as grand_filter_string
from msrc p
left outer join msrc c on c.rid_parent = p.rid_tree_mergefeld --child
and nv(c.mergetype) > 0
left outer join msrc g on g.rid_tree_mergefeld = p.rid_parent --grand parent
where nv(p.mergetype) = 0
or (p.mergetype > 0 and c.rid_tree_mergefeld > 0)
)
select d.rid
, d.rid_parent
, case
when nv(d.merge_type) = G_MTYPE_SPECIAL and strpos(d.mergetag, G_TAG_SPLIT) > 0
then substr(d.mergetag, 0, strpos(d.mergetag, G_TAG_SPLIT)) ||
substr(d.mergetag, length(d.mergetag) - length(G_TAG_E) + 1, length(d.mergetag))
else d.mergetag
end
::citext as mergetag
,d.merge_type
, d.table_name
, d.field_name
, d.filter_string
, d.order_string
, d.parent_rid
, d.parent_rid_parent
, d.parent_mergetag
, d.parent_merge_type
, d.parent_table_name
, d.parent_field_name
, d.parent_filter_string
, d.parent_order_string
, d.grand_rid
, d.grand_mergetag
, d.grand_merge_type
, d.grand_table_name
, d.grand_field_name
, d.grand_filter_string
from src d ;
--CREATE INDEX "idx_tmp_merge_init_src_type" ON tmp_merge_init_src USING btree (merge_type);
--CREATE INDEX "idx_tmp_merge_init_src_tag" ON tmp_merge_init_src USING btree (mergetag);
--HTML field types has a special meaning in the frontend. We treat them as normal fields.
update tmp_merge_init_src u
set merge_type = G_MTYPE_FIELD
where u.merge_type = G_MTYPE_HTML;
--raise notice 'After MergeMenu: %', (clock_timestamp() - m_ltime);
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf After MergeMenu SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
--Do a peek on the template and get fields we need to fetch.
if not m_returnvalues
then
if nv(octet_length(p_template)) < 2
then
raise exception E'Template document not found or blank. \r\n% File: %',octet_length(p_template), r_template.filepath;
end if;
if m_hasfilestream
then
--filesystem
select r.p_retval, r.p_errmsg
from pl_writefile(r_template.filepath, p_template) r into m_retval, m_errmsg;
if m_retval > 0
then
raise exception 'Failed to save template file to temp directory. %',m_errmsg using hint = 'in pl_writefile, while peaking template';
end if;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Before Peek SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
select r.p_retval, r.p_errmsg, r.p_result
from pl_mailmerge(format('peek_%s', p_doctype), r_template.filepath, '', ''
, 1 /*New mode, new tags*/) r into m_retval, m_errmsg, m_result;
if m_retval > 0
then
raise exception '%', m_errmsg using hint = 'in pl_mailmerge, while peaking template';
end if;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf After Peek SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
if nv(m_result) = '' --or m_result not ilike '%{%}%'
then
raise exception 'No data returned from peak.' using hint = 'in pl_mailmerge, while peaking template';
end if;
if G_DEBUG
then
perform pl_writefile(r_template.debug_peekfilename, convert_to(m_result,'utf8'));
end if;
select r.p_retval, r.p_errmsg
from f_tempfile_add(r_template.filename, p_doctype, r_template.guid, 600, m_data_rid,
m_data_prefix) r into m_retval, m_errmsg;
else
--stream
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Before Peek SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
select r.p_retval, r.p_errmsg, r.p_result, r.p_file
from pl_mailmerge(format('peek_%s', p_doctype), null, null, '', 1, p_template) r into m_retval, m_errmsg, m_result;
if m_retval > 0
then
raise exception '%', m_errmsg using hint = 'in pl_mailmerge, while peaking template';
end if;
if G_DEBUG
then
perform pl_writefile(r_template.debug_peekfilename, convert_to(m_result,'utf8'));
end if;
--perform log_event(m_funcname,format('Peek Result: %s', m_result),bt_enum('eventlog','local notice'));
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf After Peek SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
end if;
m_fields = m_result::json;
drop table if exists tmp_merge_init_fields;
create temp table tmp_merge_init_fields
--on commit drop
as
with docfields as (
select 'document'::citext as source
,btrim(btrim(r::text,' '),'"')::citext as mergetag
,1 as taglocation
from json_array_elements(m_fields->'doctags') r
union all
select 'header'::citext as source
,btrim(btrim(r::text,' '),'"')::citext as mergetag
,1 as taglocation
from json_array_elements(m_fields->'headertags') r
union all
select 'footer'::citext as source
,btrim(btrim(r::text,' '),'"')::citext as mergetag
,1 as taglocation
from json_array_elements(m_fields->'footertags') r
union all
--also the table tags in all the tables.
select r.key::citext as source
,replace(l.value::text,'"','')::citext as mergetag
,2 as taglocation
from json_each(m_fields->'tabletags') r (key,value)
left outer join json_array_elements(r.value) l (value) on json_typeof(r.value) = 'array'
where nv(l.value::text) <> ''
union all
select 'raw'::citext as source
,btrim(btrim(r::text,' '),'"')::citext as mergetag
,1 as taglocation
from json_array_elements(m_fields->'raw') r
)
select distinct
on (d.source, d.taglocation,d.mergetag)
d.source::citext as source
,(case when d.taglocation = 2 then split_part(d.source, ',', 1) else null end)::citext as tblid
,(case when d.taglocation = 2 then split_part(d.source, ',', 2) else null end)::citext as tblparent
,format('%s%s%s',G_TAG_S, replace(replace(split_part(split_part(d.mergetag, G_TAG_SPLIT,1) , G_TAG_OPER,1),G_TAG_E,''),G_TAG_S,''),G_TAG_E)::citext as mergetag
,replace(case when strpos(d.mergetag,G_TAG_SPLIT) > 0 and d.taglocation <> 5 and strpos(d.mergetag,G_TAG_E)- strpos(d.mergetag,G_TAG_SPLIT)-1 > 0
then substr(d.mergetag,strpos(d.mergetag,G_TAG_SPLIT)+1, strpos(d.mergetag,G_TAG_E)- strpos(d.mergetag,G_TAG_SPLIT)-1)
when strpos(d.mergetag,G_TAG_OPER) > 0 and strpos(d.mergetag,G_TAG_E)- strpos(d.mergetag,G_TAG_OPER)-1 > 0
then substr(d.mergetag,strpos(d.mergetag,G_TAG_OPER)+1, strpos(d.mergetag,G_TAG_E)- strpos(d.mergetag,G_TAG_OPER)-1)
else ''
end,'''','')::citext as tagvalue
,(regexp_split_to_array(replace(replace(d.mergetag,G_TAG_E,''),G_TAG_S,''),'(\'|| G_TAG_OPER || '|\' || G_TAG_SPLIT || ')' ))[2:] as operators
,d.taglocation::citext as taglocation
,d.mergetag as originalmergetag
,0:: integer as table_level
,row_number() over(order by d.source, d.mergetag) as rowid
from docfields d ;
---special update for tables linking
update tmp_merge_init_fields u
set tblparent = r.p_tblparent
, source = r.source
, tblid = r.p_tblid from (
select distinct f.tblid
, f.tblparent
, f2.tblparent as p_tblparent
, f2.tblid as p_tblid
, f.mergetag
, f2.source
from tmp_merge_init_fields f
inner join tmp_merge_init_fields f2 on f2.tblid = f.tblparent
where f.mergetag ilike '%free!tbl%'
) r
where u.tblid = r.tblid;
update tmp_merge_init_fields u
set table_level = r.table_level from (
select f1.rowid
,case when nv(f4.tblid) <> '' then 4
when nv(f3.tblid) <> '' then 3
when nv(f2.tblid) <> '' then 2
when nv(f1.tblid) <> '' then 1
else 0
end as table_level
from tmp_merge_init_fields f1
left outer join tmp_merge_init_fields f2 on f1.tblparent = f2.tblid
left outer join tmp_merge_init_fields f3 on f2.tblparent = f3.tblid
left outer join tmp_merge_init_fields f4 on f3.tblparent = f4.tblid
) r
where u.rowid = r.rowid ;
else
drop table if exists tmp_merge_init_fields;
create temp table tmp_merge_init_fields
--on commit drop
as
select distinct
on (s.mergetag)
''::citext as source
,''::citext as tblid
,''::citext as tblparent
,s.mergetag::citext as mergetag
,''::citext as tagvalue
,array[]::citext[] as operators
,1::citext as taglocation
,s.mergetag::citext as originalmergetag
from tmp_merge_init_src s
where s.merge_type in (G_MTYPE_ROOT, G_MTYPE_FIELD, G_MTYPE_AGGFIELD);
end if; --End of do a peek
--raise notice 'After Merge: %', (clock_timestamp() - m_ltime);
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf After MergeMenu SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
if not exists (
select 1
from tmp_merge_init_fields m
where nv(m.mergetag) <> ''
)
then
-- perform log_event(m_funcname,format('NO TAGS p_doctype=%s p_commtype=%s p_data_prefix=%s p_data_rid=%s'
-- ,p_doctype, p_commtype,p_data_prefix,p_data_rid),bt_enum('eventlog','local notice'));
--
p_doc = p_template;
return;
end if;
--Update [extra_filter]
/*
update tmp_merge_init_src u
set table_name = replace(u.table_name, '[extra_filter]', ifblnk(r.extra_filter, 'True'))
, parent_table_name = replace(u.parent_table_name, '[extra_filter]', ifblnk(r.extra_filter, 'True'))
, field_name = replace(u.field_name, '[extra_filter]', ifblnk(r.extra_filter, 'True'))
, parent_field_name = replace(u.parent_field_name, '[extra_filter]', ifblnk(r.extra_filter, 'True'))
, filter_string = replace(u.filter_string, '[extra_filter]', ifblnk(r.extra_filter, 'True'))
, parent_filter_string = replace(u.parent_filter_string, '[extra_filter]', ifblnk(r.extra_filter, 'True'))
from (
select f.tblid
, f.mergetag
, ltrim(ltrim(string_agg(ifblnk(s2.filter_string,'True'), ' and '),' '), 'and') as extra_filter
from tmp_merge_init_fields f
inner join tmp_merge_init_fields f2 on f2.tblid = f.tblid
inner join tmp_merge_init_src s2 on s2.mergetag = f2.mergetag
and s2.merge_type = G_MTYPE_FILTER
group by f.tblid,f.mergetag
) r
where u.mergetag = r.mergetag
;
*/
/*
---Use this code to test
select pl_writefile('/mnt/t/temp/t.docx',r.p_doc) ,r.*
from mm_proc('docx','allfieldvalues', (
select tat.maindoc
from templateattachment tat
--cross join view_blob(tat.rid_templateattachment,'templateattachment','maindoc','rid_templateattachment','utf8') v
where tat.description ilike 'Form 16 (%'
), 'TCLI',1000016) r
*/
/*
drop table if exists debug_merge_init_src;
create table debug_merge_init_src as
select * from tmp_merge_init_src
;
drop table if exists debug_merge_init_fields;
create table debug_merge_init_fields as
select * from tmp_merge_init_fields
;
*/
--------Keywords For Client,Creditor,Debt Counsellor,Trader---------------------------------------------------------
---ID replace process
if m_data_prefix::citext in ('tclc','clc')
then
m_rid_obligation = m_data_rid;
m_rid_obl = m_data_rid;
select clc.rid_adproclient
from t_adproclientcreditorl1 clc
where clc.rid_adproclientcreditorl1 = m_data_rid into m_data_rid;
m_data_prefix = 'TCLI';
end if;
if m_data_prefix::citext in ('tcli','tclc','usr','sclc')
then
if m_data_prefix::citext in ('tcli')
and not exists (
select 1
from t_adproclient cli
where cli.rid_adproclient = m_data_rid
)
then
raise exception 'Client % does not exists.', m_data_rid;
end if;
-----------------------------------------------------------[CHANGE ID: 29078] 14/07/2020 14:54 Begin
if m_data_prefix::citext in ('usr')
then
select usr.login
from users usr
where usr.rid_user = m_data_rid into m_user;
m_data_rid = 0;
end if;
if m_rid_comm > 0 and nv(m_rid_obligation) = 0
then
select ct.rid_obligation
from commattachment ct
where ct.tableprefix = 'COM'
and ct.rid_parent = m_rid_comm
and ct.doclink = 1
and ct.rid_obligation > 0
order by ct.rid_templateattachment desc limit 1
into m_rid_obligation ;
end if;
/*if r_comm.data_prefix = 'RPC'
then
select usr.login
from remotepc rpc
inner join users usr on usr.rid_user = rpc.rid_user
where rpc.rid_remotepc = r_comm.data_rid
into m_user
;
m_data_rid = 0;
end if;*/
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Merge Replace SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
for r_lp in (
select '[rid_obligation]'::citext as key
,ifblnk(m_rid_obligation,0)::citext as value
)
loop
update tmp_merge_init_src u
set table_name = replace(u.table_name, r_lp.key, r_lp.value)
, parent_table_name = replace(u.parent_table_name, r_lp.key, r_lp.value)
, field_name = replace(u.field_name, r_lp.key, r_lp.value)
, parent_field_name = replace(u.parent_field_name, r_lp.key, r_lp.value)
, filter_string = replace(u.filter_string, r_lp.key, r_lp.value)
, parent_filter_string = replace(u.parent_filter_string, r_lp.key, r_lp.value)
;
end loop;
-----------------------------------------------------------[CHANGE ID: 29078] 14/07/2020 14:54 End
for r_lp in (
with keywords as (
select distinct r.v[1]::citext as colname
from tmp_merge_init_src f
cross join regexp_matches(format('%s %s %s %s %s %s',f.table_name,f.parent_table_name,f.field_name,f.parent_field_name,f.parent_filter_string,f.filter_string)
, '\[(.*?)\]', 'ig') r(v)
where m_data_prefix = 'tcli'
and length(nv(r.v[1])) > 2
)
,keyworddata as (
select r.j
from exec(format('select (''{ "debugflag": "%s"'' %s || ''}'')::json from t_adproclient cli where cli.rid_adproclient = %s'
,G_DEBUG
,(select string_agg(format('|| '',"%s":"'' || nv(%s)::text || ''"''',format('[%s]',k.colname), k.colname), E'\r\n') from keywords k
where nv(k.colname) not in (
'rid_communication'
,'rid_commattachment'
,'rid_obl_filter'
,'exec_user'
,'extra_filter'
,'rid_user'
,'p_doctype'
,'rid_obligation'
----!!!!!Remeber to add the records here to exclude if the already have a value below
)
)
,m_data_rid
)
) r(j json)
)
select j.key::citext as key
, btrim(j.value::text,'"')::text::citext as value
from keyworddata d
cross join json_each(d.j) j(key,value)
where j.key <> ''
-----Some extra generic keywords
union all
select '[rid_communication]'::citext as key
,ifblnk(m_rid_comm,0)::citext as value
union all
select '[rid_obl_filter]'::citext as key
,ifblnk(m_rid_obl,0)::citext as value
union all
select '[exec_user]'::citext as key
,nv(m_user)::citext as value
union all
select '[extra_filter]'::citext as key
,'True'::citext as value
union all
select '[rid_commattachment]'::citext as key
,ifblnk(m_rid_commattachment,0)::citext as value --[CHANGE ID: 28878] 23/06/2020 11:33
/* union all
select '[rid_remotepc]'::citext as key
,nv(r_comm.data_rid)::citext as value --[CHANGE ID: 29078] 15/07/2020 9:36*/
union all
select '[p_doctype]'::citext as key
,ifblnk(p_doctype,'docx')::citext as value
)
loop
update tmp_merge_init_src u
set table_name = replace(u.table_name, r_lp.key, r_lp.value)
, parent_table_name = replace(u.parent_table_name, r_lp.key, r_lp.value)
, field_name = replace(u.field_name, r_lp.key, r_lp.value)
, parent_field_name = replace(u.parent_field_name, r_lp.key, r_lp.value)
, filter_string = replace(u.filter_string, r_lp.key, r_lp.value)
, parent_filter_string = replace(u.parent_filter_string, r_lp.key, r_lp.value)
;
end loop;
else
select string_agg(distinct format('[%s]', r.v[1]::text), ',')
, count(1)
from tmp_merge_init_src f
cross join regexp_matches(
format('%s %s %s %s %s %s', f.table_name, f.parent_table_name, f.field_name, f.parent_field_name,
f.parent_filter_string, f.filter_string)
, '\[(.*?)\]', 'ig') r(v) into m_errmsg,m_retval;
if m_retval > 0
then
raise exception E'The following data fields could not be found for prefix % \r\n%', ifblnk(m_data_prefix, 'Null'), m_errmsg using hint = 'in ID replace process';
end if;
end if;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Merge Filter SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
--------Basic Fields---------------------------------------------------------------------------------
m_execstr = '';
m_execfilter = '';
m_blankexec = '';
m_comma = '';
for r_lp in (
with fields as (
select f.mergetag
,f.merge_type
,f.table_name
,f.field_name
,f.filter_string
,f.parent_mergetag
,f.parent_merge_type
,f.parent_table_name
,f.parent_field_name
,f.parent_filter_string
from tmp_merge_init_src f
)
,filtereddocfields as (
select distinct on (d.originalmergetag, d.taglocation)
d.source
,d.tblid
,d.tblparent
,d.mergetag as joinmergetag --- because opertators are filtered out already, we join without operators to be able to find the tag.
,(case when strpos(d.originalmergetag, G_TAG_OPER) > 0 then d.originalmergetag
else d.mergetag
end)::citext as mergetag
,replace(d.tagvalue,'''','') as tagvalue
,d.taglocation
,d.originalmergetag
,d.operators
from tmp_merge_init_fields d
)
select
f.merge_type
,f.table_name
,f.field_name
,f.filter_string
,f.parent_mergetag
,f.parent_merge_type
,f.parent_table_name
,f.parent_field_name
,f.parent_filter_string
,d.mergetag
,replace(d.tagvalue,'''','') as tagvalue
,d.source
,d.tblid
,d.operators
,row_number() over(partition by (case
when f.merge_type IN (G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD,G_MTYPE_PICTURE)
then G_MTYPE_FIELD
else f.merge_type
end)
, f.parent_table_name
, f.table_name
, f.parent_filter_string
, f.filter_string
order by (case
when f.merge_type IN (G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD,G_MTYPE_PICTURE)
then G_MTYPE_FIELD
else f.merge_type
end) asc
, f.parent_table_name
, f.table_name
, f.field_name
) as rn
---Additional fields
,''::citext as ops_string
from fields f
inner join filtereddocfields d on d.joinmergetag = f.mergetag
where f.merge_type in (G_MTYPE_ROOT,G_MTYPE_FIELD,G_MTYPE_AGGFIELD,G_MTYPE_PICTURE, G_MTYPE_CONDFIELD) --all except tables
and (f.merge_type <> G_MTYPE_AGGFIELD
or f.merge_type = G_MTYPE_AGGFIELD
and nv(d.source) = ''
)
order by (case when f.merge_type IN (G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD,G_MTYPE_PICTURE)
then G_MTYPE_FIELD
else f.merge_type
end) asc
, f.parent_table_name
, f.table_name
, rn desc
)
loop
--raise notice 'Fields: %', r_lp;
if nv(r_lp.field_name) = '' and r_lp.merge_type not in (G_MTYPE_TBLROOT,G_MTYPE_SPECIAL)
then
if G_DEBUG
then
perform log_event(m_funcname,format('Blank field name for p_doctype=%s, p_commtype=%s, p_data_prefix=%s, p_data_rid=%s
field_name=%s, merge_type=%s, table_name=%s
' ,p_doctype, p_commtype,p_data_prefix,p_data_rid
,r_lp.field_name,r_lp.merge_type,r_lp.table_name
--,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text
),bt_enum('eventlog','local notice'));
end if;
--raise exception 'Blank field name for record %', r_lp;
continue ;
end if;
if nv(r_lp.ops_string) = ''
then
r_lp.ops_string = r_lp.field_name;
end if;
for r_tmp in (
select o.r as op
,split_part(o.r, '=', 1) as opname
,split_part(o.r, '=', 2) as opval
from unnest(r_lp.operators) with ordinality o(r,i)
order by o.i asc
)
loop
r_lp.ops_string = mailmerge_rule(r_lp.ops_string::citext, r_tmp.opname::citext, r_tmp.opval::citext, r_lp.mergetag::citext);
end loop;
--perform log_event(m_funcname,format('mailmerge_rules %s',r_lp.ops_string),bt_enum('eventlog','local notice'));
if r_lp.merge_type = G_MTYPE_AGGFIELD
then
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',%s::text, 'type', '%s')::text %s$S$
,m_execstr,m_comma,r_lp.mergetag
,r_lp.ops_string, r_lp.merge_type, E'\r\n');
elseif r_lp.merge_type = G_MTYPE_PICTURE
then
m_execstr = format($S$%s|| '%s"%s":'
|| json_build_object('value',%s::text, 'type', '%s'
, 'w', mailmerge_specialfield('width', '%s', %s) ,'h', mailmerge_specialfield('height', '%s', %s))::text %s$S$
,m_execstr,m_comma,r_lp.mergetag,r_lp.field_name, r_lp.merge_type
,r_lp.mergetag,quote_nullable(m_data_rid),r_lp.mergetag,quote_nullable(m_data_rid), E'\r\n');
elseif r_lp.merge_type = G_MTYPE_TBLFIELD
then
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',json_agg(%s::text), 'type', '%s')::text %s$S$
,m_execstr,m_comma,r_lp.mergetag
,r_lp.ops_string
,r_lp.merge_type, E'\r\n');
elseif r_lp.merge_type = G_MTYPE_SPECIAL
then
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',%s, 'type', '%s')::text %s$S$,m_execstr,m_comma,r_lp.mergetag,quote_literal(r_lp.tagvalue), r_lp.merge_type, E'\r\n');
else
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',%s::text, 'type', '%s')::text %s$S$
,m_execstr,m_comma,r_lp.mergetag
,r_lp.ops_string
,r_lp.merge_type, E'\r\n');
end if;
m_execfilter = format('%s %s',nv(m_execfilter), r_lp.filter_string);
--We use this to fill in blanks.
m_blankexec = format($S$%s|| '%s"%s":' || json_build_object('value','', 'type', '%s')::text %s$S$,m_blankexec,m_comma,r_lp.mergetag, r_lp.merge_type, E'\r\n');
if r_lp.rn = 1
then
if ifblnk(r_lp.parent_table_name,'') = ''
then
m_execstr = format(E'select (''{'' %s \r\n || ''}'')::json ;',m_execstr );
else
select string_agg(s.filter_string, ' ')
from tmp_merge_init_fields f
inner join tmp_merge_init_src s on s.mergetag = f.mergetag
and s.merge_type = G_MTYPE_FILTER
where f.source = r_lp.source
and exists ( --make sure there is a parent, else this breaks. It means there will be not parent table.
select 1
from tmp_merge_init_src s2
where s2.rid = s.rid_parent)
into m_tablefilter ;
m_execstr = format(E'select (''{'' %s \r\n || ''}'')::json \r\nfrom %s \r\n%s;'
,m_execstr, r_lp.parent_table_name,ifblnk(r_lp.parent_filter_string, ' where 1=1 ') || nv(m_execfilter) || nv(m_tablefilter) );
end if;
m_blankexec = format(E'select (''{'' %s \r\n || ''}'')::json \r\n;',m_blankexec );
m_debug_exestr = nv(m_debug_exestr) || E'\r\n----'|| r_lp.parent_table_name ||E'\r\n' || nv(m_execstr) || E'\r\n';
select r.str::json
from exec(m_execstr) r(str json) into m_json;
if m_json is null
then
select r.str::json
from exec(m_blankexec) r(str json) into m_json;
end if;
if nv(m_json_full::text) <> ''
then
m_json_full = (m_json_full::jsonb || m_json::jsonb)::json;
else
m_json_full = m_json;
end if;
m_tablefilter = '';
m_execfilter = '';
m_execstr = '';
m_blankexec = '';
m_comma = '';
end if;
if nv(m_comma) = '' and length(m_execstr) > 2
then
m_comma = ',';
end if;
end loop;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Complex Fields SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
--------Complex Fields---------------------------------------------------------------------------------
m_execfilter = '';
m_tablefilter = '';
m_execstr = '';
m_blankexec = '';
m_comma = '';
m_exec_orderstr = '';
-----@2023-10-24 -
---This code must move the tag of a parent col in the child table back to the parent table in order to complete the join.
/*
with a as (
select d.mergetag as mt
,d.source
,d.tblparent
,d.tblid
,d.table_level
,d.rowid
,d.taglocation
,f.*
from tmp_merge_init_src f
inner join tmp_merge_init_fields d on d.mergetag = f.mergetag
where f.merge_type = 2
), aa as (
select
(select count(1) from a b where b.rid_parent = a.rid_parent and b.tblid = a.tblid) as cnt
,*
from a
), b as (
select aa.rid
,aa.rowid
,aa.rid_parent
,aa.tblid
,aa.cnt < (select b.cnt from aa b where b.rid_parent = aa.rid_parent order by b.cnt desc limit 1) as oddone
,(select b.tblid from aa b where b.rid_parent = aa.rid_parent order by b.cnt desc limit 1) as newtblid
,(select b.tblparent from aa b where b.rid_parent = aa.rid_parent order by b.cnt desc limit 1) as newtblparent
,(select b.source from aa b where b.rid_parent = aa.rid_parent order by b.cnt desc limit 1) as newsource
,(select b.table_level from aa b where b.rid_parent = aa.rid_parent order by b.cnt desc limit 1) as new_table_level
,aa.mt
from aa
)
update tmp_merge_init_fields f
set tblid = b.newtblid
,tblparent = b.newtblparent
,source = b.newsource
,table_level = b.new_table_level
from b
where f.rowid = b.rowid
;
*/
select array_agg(f.rid)
from tmp_merge_init_src f
where f.grand_merge_type = G_MTYPE_TBLROOT
and f.merge_type = G_MTYPE_TBLROOT into a_tblroot;
if a_tblroot is null then a_tblroot = array[-1];
end if;
m_json_full_complex = jsonb_build_object();
--a_tblroot = array[-1];
BEGIN
for r_lp_t in (
with fields as (
select f.rid
,f.mergetag
,f.merge_type
,f.table_name
,f.field_name
,f.filter_string
,f.parent_rid
,f.parent_mergetag
,f.parent_merge_type
,f.parent_table_name
,f.parent_field_name
,f.parent_filter_string
,f.grand_rid
,f.grand_mergetag
,f.grand_merge_type
,f.grand_table_name
,f.grand_field_name
,f.grand_filter_string
,f.order_string
,f.parent_order_string
,newid()::citext as guid
from tmp_merge_init_src f
where f.rid <> any(a_tblroot)
and f.parent_rid <> any(a_tblroot)
and f.grand_rid <> any(a_tblroot)
)
,joined as (
select f.rid
,f.merge_type
,f.table_name
,f.field_name
,f.filter_string
,f.parent_rid
,f.parent_mergetag
,f.parent_merge_type
,f.parent_table_name
,f.parent_field_name
,f.parent_filter_string
,f.grand_rid
,f.grand_mergetag
,f.grand_merge_type
,f.grand_table_name
,f.grand_field_name
,f.grand_filter_string
,f.order_string
,f.parent_order_string
,replace(nv(d.tagvalue),'''','')::citext as tagvalue
,nv(d.source)::citext as source
,d.tblid::citext as tblid
,d.tblparent::citext as tblparent
,d.mergetag as joinmergetag --- because opertators are filtered out already, we join without operators to be able to find the tag.
,(case when strpos(d.originalmergetag, G_TAG_OPER) > 0 then d.originalmergetag
else d.mergetag
end)::citext as mergetag
,''::citext as ops_string
,d.operators
,d.table_level
,f.guid
from fields f
inner join tmp_merge_init_fields d on d.mergetag = f.mergetag
where f.merge_type in (G_MTYPE_ROOT,G_MTYPE_TBLFIELD,G_MTYPE_TBLROOT,G_MTYPE_AGGFIELD ) --all tables
)
select e.*
,row_number() over(partition by
e.source
, case when e.merge_type in (G_MTYPE_SPECIAL, G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD )
then G_MTYPE_TBLFIELD
else e.merge_type
end
, e.parent_table_name
, e.table_name
, e.parent_filter_string
, e.filter_string
order by
e.source
, case
when e.merge_type in (G_MTYPE_SPECIAL, G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD )
then G_MTYPE_TBLFIELD
when e.merge_type IN (G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD,G_MTYPE_PICTURE)
then G_MTYPE_FIELD
else e.merge_type
end
, e.parent_table_name, e.table_name, e.field_name) as rn
from joined e
where nv(e.tblparent) in ('0','')
order by
e.source
,case when e.merge_type in (G_MTYPE_SPECIAL, G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD )
then G_MTYPE_TBLFIELD
when e.merge_type IN (G_MTYPE_CONDFIELD,G_MTYPE_AGGFIELD,G_MTYPE_PICTURE)
then G_MTYPE_FIELD
else e.merge_type
end
,e.parent_table_name
,e.table_name
,rn desc
)
loop
-- perform log_event(m_funcname,format(' Tables %s=%s src=%s rn=%s' ,p_data_prefix,p_data_rid
-- ,r_lp_t.source,r_lp_t.rn
-- ),bt_enum('eventlog','local notice')
-- --,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text
-- );
if r_lp_t.table_name = any(a_inner_selected) and nv(r_lp_t.table_name ) <> ''
then
raise notice 'Table used as inner table: %', r_lp_t.table_name;
continue;
end if;
--raise notice 'Field:% Table:% Tag: % Type: %', r_lp_t.field_name, r_lp_t.table_name, r_lp_t.mergetag, r_lp_t.merge_type;
if nv(r_lp_t.field_name) = '' and r_lp_t.merge_type not in (G_MTYPE_TBLROOT,G_MTYPE_SPECIAL)
then
if G_DEBUG
then
perform log_event(m_funcname,format('Blank field name on Complex merge for p_doctype=%s, p_commtype=%s, p_data_prefix=%s, p_data_rid=%s
field_name=%s, merge_type=%s, table_name=%s
' ,p_doctype, p_commtype,p_data_prefix,p_data_rid
,r_lp.field_name,r_lp.merge_type,r_lp.table_name),bt_enum('eventlog','local notice')
--,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text
);
end if;
--raise exception 'Blank field name for record %', r_lp;
continue;
end if;
if nv(m_exec_orderstr) = '' and nv(r_lp_t.parent_order_string) <> ''
then
m_exec_orderstr = r_lp_t.parent_order_string;
--raise notice 'Applying order % by for % %.', r_lp_t.parent_order_string, r_lp_t.parent_table_name,r_lp_t.field_name;
/*
select s.parent_order_string
from tmp_merge_init_fields f
inner join tmp_merge_init_src s on s.parent_rid = r_lp_t.rid
and s.merge_type = G_MTYPE_TBLROOT
and nv(s.parent_order_string) <> ''
where f.source = r_lp_t.source
limit 1
into m_exec_orderstr;
*/
end if;
if nv(r_lp_t.ops_string) = ''
then
r_lp_t.ops_string = r_lp_t.field_name;
end if;
for r_tmp in (
select o.r as op
,split_part(o.r, '=', 1) as opname
,split_part(o.r, '=', 2) as opval
from unnest(r_lp_t.operators) with ordinality o(r,i)
order by o.i asc
)
loop
r_lp_t.ops_string = mailmerge_rule(r_lp_t.ops_string::citext, r_tmp.opname::citext, r_tmp.opval::citext, r_lp_t.mergetag::citext);
end loop;
if r_lp_t.merge_type in (G_MTYPE_TBLFIELD, G_MTYPE_CONDFIELD)
then
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',json_agg(%s::text %s), 'type', '%s')::text %s$S$
,m_execstr,m_comma,r_lp_t.mergetag
,r_lp_t.ops_string
, m_exec_orderstr, r_lp_t.merge_type, E'\r\n');
elseif r_lp_t.merge_type = G_MTYPE_SPECIAL--special fields
then
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',%s, 'type', '%s')::text %s$S$
,m_execstr,m_comma,r_lp_t.mergetag,quote_literal(r_lp_t.tagvalue), r_lp_t.merge_type, E'\r\n');
--raise notice 'Special Field: %s',r_lp_t;
elseif r_lp.merge_type = G_MTYPE_PICTURE
then
m_execstr = format($S$%s|| '%s"%s":'
|| json_build_object('value',%s::text, 'type', '%s'
, 'w', mailmerge_specialfield('width', '%s', %s) ,'h', mailmerge_specialfield('height', '%s', %s))::text %s$S$
,m_execstr,m_comma,r_lp.mergetag,r_lp.field_name, r_lp.merge_type
,r_lp.mergetag,quote_nullable(m_data_rid),r_lp.mergetag,quote_nullable(m_data_rid), E'\r\n');
elseif nv(r_lp_t.field_name) <> ''
then
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',%s::text, 'type', '%s')::text %s$S$
,m_execstr,m_comma,r_lp_t.mergetag
, r_lp_t.ops_string
, r_lp_t.merge_type, E'\r\n');
end if;
m_execfilter = format('%s %s',nv(m_execfilter), r_lp_t.filter_string);
--We use this to fill in blanks.
m_blankexec = format($S$%s|| '%s"%s":' || json_build_object('value','', 'type', '%s')::text %s$S$,m_blankexec,m_comma,r_lp_t.mergetag, r_lp_t.merge_type, E'\r\n');
if r_lp_t.rn = 1
then
--Inner level tables (2)
--raise notice 'Begin: parent: %', r_lp_t;
for r_lp_c in (
select f.rid
,max(f.merge_type) as merge_type
,format('%s', max(ifblnk(d.tblid,f.table_name)))::citext as subname
,($S
$(select ('{'|| $S$ || string_agg(format($SS$'"%1$s": ' || json_build_object('value', json_agg(%2$s::text),
'type',
'%3$s'
)
:
:
text
$SS$,
c
.
mergetag,
c
.
field_name,
c
.
merge_type
),
'|| '',''||'
)
||
$S$
||
'}'
)
:
:
json
from $S$ || max (
f
.
table_name
)
||
' '
||
ifblnk (
max
(
f
.
filter_string
),
'where 1=1'
)
||
')'
)
:
:
citext as qry , (
$S
$(select ('{'|| $S$ || string_agg(format($SS$'"%1$s": ' || json_build_object('value', '[]', 'type','%3$s')
:
:
text
$SS$,
c
.
mergetag,
c
.
field_name,
c
.
merge_type
),
'|| '',''||'
)
||
$S$
||
'}'
)
:
:
json $S$ || ')' ) : : citext as qryblnk , nv (
max
(
f
.
parent_order_string
)
)
:
:
citext as parent_order_string
from tmp_merge_init_src f
inner
join tmp_merge_init_src c
on c . rid_parent = f . rid and c . merge_type in (
G_MTYPE_TBLFIELD
)
inner
join tmp_merge_init_fields d
on d . mergetag = c . mergetag and d . tblparent = r_lp_t . tblid
where f . grand_rid = r_lp_t . parent_rid and f . merge_type = G_MTYPE_TBLROOT --and f.parent_rid = any(a_tblroot) --and d.table_level > 0
group by f . rid ) loop
raise notice 'Inner Loop: %', r_lp_c . qry;
a_inner_selected = array_append(a_inner_selected, r_lp_t.table_name);
m_execstr = format($S$%s|| '%s"%s":' || json_build_object('value',json_agg(%s::json %s)::json, 'type', '%s')::text %s$S$
,m_execstr,',',r_lp_c.subname,r_lp_c.qry, r_lp_c.parent_order_string, r_lp_c.merge_type, E'\r\n');
m_blankexec = format($S$%s|| '%s"%s":' || json_build_object('value',json_agg(%s::json %s)::json, 'type', '%s')::text %s$S$
,m_blankexec,',',r_lp_c.subname,r_lp_c.qryblnk, r_lp_c.parent_order_string, r_lp_c.merge_type, E'\r\n');
end loop;
if ifblnk(r_lp_t.parent_table_name,'') = ''
then
m_execstr = format(E'select (''{'' %s \r\n || ''}'')::json ;',m_execstr );
else
select string_agg(s.filter_string, ' ')
from tmp_merge_init_fields f
inner join tmp_merge_init_src s on s.mergetag = f.mergetag
and s.merge_type = G_MTYPE_FILTER
where f.source = r_lp_t.source into m_tablefilter ;
m_execstr = format(E'select (''{'' %s \r\n || ''}'')::json \r\nfrom %s \r\n%s;'
,m_execstr, r_lp_t.parent_table_name,ifblnk(r_lp_t.parent_filter_string, ' where 1=1 ') || nv(m_execfilter) || nv(m_tablefilter) );
end if;
m_blankexec = format(E'select (''{'' %s \r\n || ''}'')::json \r\n;',m_blankexec );
select r.p_retval, r.p_errmsg, r.p_json - > 'str'
from exec_json(m_execstr, 'str json') r into m_retval,m_errmsg, m_json;
if m_json is null
then
select r.p_retval, r.p_errmsg, r.p_json - > 'str'
from exec_json(m_execstr, 'str json') r into m_retval,m_errmsg, m_json;
end if;
m_debug_exestr = nv(m_debug_exestr) || E'\r\n/*'|| nv(r_lp_t.parent_table_name) || ' len:' || nv(length(m_json::text)) ||E'*/ \r\n' || nv(m_execstr) || E'\r\n ';
if m_json_full_complex is null
then
m_json_full_complex = jsonb_build_object(r_lp_t.tblid::text,m_json);
end if;
if (m_json_full_complex->r_lp_t.tblid::text) is null
then
m_json_full_complex = jsonb_set(m_json_full_complex, format('{%s}',r_lp_t.tblid)::text[], m_json::jsonb,true);
else
m_json_full_complex = jsonb_set(m_json_full_complex, format('{%s}',r_lp_t.tblid)::text[], _jsonb_object_cat(m_json_full_complex->r_lp_t.tblid,m_json::jsonb),true);
end if;
-- perform log_event(m_funcname,format('Complex Tables %s=%s m_json_full_complex=%s' ,p_data_prefix,p_data_rid
-- ,m_json_full_complex::text
-- ),bt_enum('eventlog','local notice')
-- --,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text
-- );
m_execfilter = '';
m_execstr = '';
m_blankexec = '';
m_exec_orderstr = '';
m_comma = '';
m_tablefilter = '';
end if;
if nv(m_comma) = '' and length(m_execstr) > 2
then
m_comma = ',';
end if;
end loop;
if G_DEBUG
then
perform pl_writefile(r_template.debugsql_filename, convert_to(m_debug_exestr,'utf8'));
end if;
EXCEPTION
WHEN others THEN
GET STACKED DIAGNOSTICS
m_errmsg = MESSAGE_TEXT
,m_errcontext = PG_EXCEPTION_CONTEXT
,m_errdetail = PG_EXCEPTION_DETAIL
,m_errhint = PG_EXCEPTION_HINT
,m_errstate = RETURNED_SQLSTATE;
m_errmsg = format(E'Merge failed to complete. Merge fields are not setup correctly. \r\nPlease check the template. \r\nThere could be table merge tags outside of a table. \r\nDetail Error: \r\n%s',m_errmsg);
m_errmsg = nv(m_errmsg) || format(E'\r\nExecString: %s ', ifblnk(m_execstr,m_debug_exestr));
m_errmsg = nv(m_errmsg) || format(E'\r\nError Detail: %s , %s, %s, %s', m_errdetail,m_errcontext,m_errhint,m_errstate);
if G_DEBUG
then
m_errmsg = format(E'%s \r\nDebug file: %s',m_errmsg, r_template.debugsql_filename);
perform pl_writefile(r_template.debugsql_filename, convert_to(m_debug_exestr,'utf8'));
end if;
p_retval = 1;
p_errmsg = m_errmsg;
m_json_full_complex = _jsonb_object_cat(m_json_full_complex, jsonb_build_object('p_retval',p_retval,'p_errmsg',p_errmsg));
return;
--raise exception '%', m_errmsg using hint = 'in merge jsonbuild process';
END;
--------------------------------------------------------------------------------------------------------
m_json_full = json_build_object('fields',m_json_full, 'complexfields',m_json_full_complex);
if G_DEBUG
then
perform pl_writefile(r_template.debug_filename, convert_to(m_json_full::text,'utf8'));
end if;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Complex Fields 2SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
if m_returnvalues
then
p_doc = convert_to(m_json_full::text, 'utf8');
p_docguid = 'json:see->p_doc';
else
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf Before pl_mailmerge SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
if m_hasfilestream
then
--filesystem
select r.p_retval
, r.p_errmsg
, r.p_result
from pl_mailmerge(format('merge_%s', p_doctype), r_template.filepath, r_doc.filepath, m_json_full::text,
1 /*New mode, new tags*/) r into r_retval;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf After pl_mailmerge SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
if r_retval.p_retval = 1
then
raise '%',r_retval.p_errmsg;
elseif r_retval.p_retval = 2
then
p_retval = 2;
p_errmsg = r_retval.p_errmsg;
end if;
select r.p_retval, r.p_errmsg
from f_tempfile_add(r_doc.filepath, p_doctype, r_doc.guid, 600, m_data_rid, m_data_prefix) r into m_retval, m_errmsg;
p_docguid = r_doc.guid;
select r.p_outfile, r.p_retval, r.p_errmsg
from pl_readfile(r_doc.filepath) r into p_doc, m_retval, m_errmsg;
if m_retval = 0
then
perform pl_deletefile(r_doc.filepath);
perform pl_deletefile(r_template.filepath);
end if;
else
m_ltime = clock_timestamp();
--
-- select r.p_retval, r.p_errmsg
-- from f_tempfile_add(null, 'template', r_template.guid, 600,m_data_rid, m_data_prefix,r_template.blob) r
-- into m_retval, m_errmsg;
--
-- perform log_event(m_funcname,format('Dbg D:%s J:%s template:%s', p_doctype, m_json_full, r_template.guid)
-- ,bt_enum('eventlog','local notice'));
-- --stream
select r.p_retval
, r.p_errmsg
, r.p_result
, r.p_file
from pl_mailmerge(format('merge_%s', p_doctype), null, null, m_json_full::text
, 1 /*New mode, new tags*/, r_template.blob) r into r_retval;
if G_BENCHMARK = 1
then
perform log_event(m_funcname,format('Perf After pl_mailmerge Stream SinceStart: %s Duration: %s', clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
r_doc.blob = r_retval.p_file;
p_doc = r_retval.p_file;
if r_retval.p_retval = 1
then
raise '%',r_retval.p_errmsg;
elseif r_retval.p_retval = 2
then
p_retval = 2;
p_errmsg = r_retval.p_errmsg;
end if;
end if;
end if;
if G_BENCHMARK in (1,2)
then
perform log_event(m_funcname,format('Perf Merge End (%s,%s) SinceStart: %s Duration: %s',p_doctype,p_data_rid, clock_timestamp() - m_start, clock_timestamp() - m_ltime),bt_enum('eventlog','local notice'));
m_ltime = clock_timestamp();
end if;
EXCEPTION
WHEN others THEN
GET STACKED DIAGNOSTICS
m_errmsg = MESSAGE_TEXT
,m_errcontext = PG_EXCEPTION_CONTEXT
,m_errdetail = PG_EXCEPTION_DETAIL
,m_errhint = PG_EXCEPTION_HINT
,m_errstate = RETURNED_SQLSTATE;
p_errmsg := get_err_msg(m_funcname, m_errmsg, m_errcontext, m_errdetail, m_errhint, m_errstate);
p_retval = 1;
p_errmsg = nv(p_errmsg) || nv(format(E'\r\n p_doctype:%s, p_commtype:%s, p_data_prefix:%s, p_data_rid:%s, p_filterdata:%s'
,p_doctype,p_commtype,p_data_prefix,p_data_rid, p_filterdata));
if G_DEBUG
then
perform pl_writefile(r_template.debugsql_filename, convert_to(m_debug_exestr,'utf8'));
perform pl_writefile(r_template.debug_filename, convert_to(m_json_full::text,'utf8'));
end if;
END;
$$;