1571 lines
55 KiB
PL/PgSQL
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;
|
|
$$;
|