Загрузка данных
CREATE OR REPLACE PROCEDURE ws.sp_request_root(IN p_s_request text, OUT p_s_responce text, OUT p_s_resp_status text, OUT p_s_resp_msg text)
LANGUAGE plpgsql
AS $procedure$
declare
sExecProc text;
nMethodId bigint;
nMethodLogId bigint;
nMethodLogLookupId bigint;
sRequestHash ws.method_log.req_hash%type;
sDbLinkDb text;
sStakedText01 text;
sStakedText02 text;
sStakedText03 text;
begin
p_s_responce := null;
p_s_resp_status := '200';
p_s_resp_msg := 'OK';
-----------------------------------------
-- base chk
-----------------------------------------
begin
sExecProc := lower( trim( p_s_request::json ->> 'RequestParams_Method' ) );
exception when OTHERS then
p_s_resp_status := '400';
p_s_resp_msg := 'Передан невалидный JSON';
end;
if ( sExecProc is null and p_s_resp_status = '200' ) then
p_s_resp_status := '400';
p_s_resp_msg := 'Не указан RequestParams_Method';
end if;
if ( to_regproc(sExecProc) is null and p_s_resp_status = '200' ) then
p_s_resp_status := '405';
p_s_resp_msg := concat('Не найден целевой объект', ' "' || sExecProc || '"' );
end if;
if ( p_s_resp_status <> '200' ) then
return;
end if;
-----------------------------------------
-- get/add methods.id from/to methods list
-----------------------------------------
begin
select m.id, nullif(m.dblink_db, '')
into STRICT nMethodId, sDbLinkDb
from ws.methods m
where m.code = sExecProc;
exception when NO_DATA_FOUND then
nMethodId := nextval('ws.seq_common'::regclass);
insert into ws.methods(id, code)
values(nMethodId, sExecProc);
end;
if not exists ( select 1
from integration.list_db_for_dblink l
where l."describe" = sDbLinkDb ) then
raise notice 'Не найден указанный на методе dblink = %', sDbLinkDb;
sDbLinkDb := null;
end if;
-----------------------------------------
-- main routine
-----------------------------------------
nMethodLogId := nextval('ws.seq_common'::regclass);
begin
sRequestHash := md5( p_s_request :: jsonb :: text );
exception when OTHERS then
sRequestHash := md5( p_s_request );
end;
insert into ws.method_log(id, method_id, req_hash)
values(nMethodLogId, nMethodId, sRequestHash);
-- get cached responce
select ml.id, p.part_value
into nMethodLogLookupId, p_s_responce
from ws.method_log ml
join ws.methods m on m.id = ml.method_id
join ws.method_log_parts p on (p.method_log_id = ml.id and p.part_type = 'resp')
where ml.method_id = nMethodId
and ml.req_hash = sRequestHash
and ml.resp_status = '200'
and coalesce(ml.cache_type, 0) = 0
and ml.id < nMethodLogId
and ml.start_dt >= clock_timestamp() - m.resp_lookup_sec * interval '1 second'
order by ml.start_dt desc
limit 1;
--
if ( nMethodLogLookupId is null ) then
insert into ws.method_log_parts(method_log_id, part_type, part_value)
values(nMethodLogId, 'req', p_s_request);
-- main call
begin
if exists (select 1
from information_schema.routines r
where r.routine_name = lower(split_part(sExecProc, '.', 2))
and r.routine_schema = lower(split_part(sExecProc, '.', 1))
and r.routine_type = 'PROCEDURE'
) then
if sDbLinkDb is not null then
sExecProc := format('call %s(%L, null)', sExecProc, p_s_request);
sExecProc := format('select * from dblink(integration.dblink_string_connect(%L), %L) AS (output_val text)', sDbLinkDb, sExecProc);
-- raise notice '%', sExecProc;
execute sExecProc INTO STRICT p_s_responce;
else
execute 'CALL ' || sExecProc || ' ($1, $2)' INTO p_s_responce USING p_s_request, p_s_responce;
end if;
else
sExecProc := format('select t.* from %s(%L) t', sExecProc, p_s_request);
if sDbLinkDb is not null then
sExecProc := format('select tt.* from integration.get_result_from_dyn_dblink(%L, %L) tt', sDbLinkDb, sExecProc);
end if;
-- raise notice '%', sExecProc;
execute sExecProc INTO STRICT p_s_responce;
end if;
-- close log
insert into ws.method_log_parts(method_log_id, part_type, part_value)
values(nMethodLogId, 'resp', p_s_responce);
EXCEPTION WHEN OTHERS
THEN
GET STACKED DIAGNOSTICS
sStakedText01 = MESSAGE_TEXT,
sStakedText02 = PG_EXCEPTION_DETAIL,
sStakedText03 = PG_EXCEPTION_CONTEXT;
p_s_resp_msg := left(concat( sStakedText01,
E'\r\n' || sStakedText02,
E'\r\n' || sStakedText03 ), 512);
p_s_resp_status := '500';
END;
update ws.method_log l
set end_dt = clock_timestamp(),
resp_status = p_s_resp_status,
resp_msg = p_s_resp_msg
where l.id = nMethodLogId;
else
update ws.method_log l
set end_dt = clock_timestamp(),
resp_status = p_s_resp_status,
resp_msg = p_s_resp_msg,
cache_type = 1,
cache_method_log_id = nMethodLogLookupId
where l.id = nMethodLogId;
end if;
end;
$procedure$