199 lines
6.4 KiB
PL/PgSQL
199 lines
6.4 KiB
PL/PgSQL
select * from dropall('migrations_run','meta');
|
|
CREATE OR REPLACE FUNCTION meta.migration_run(
|
|
p_id_migration_model integer default null
|
|
,p_priority_start integer default 0
|
|
,p_priority_end integer default 10000
|
|
,INOUT p_info jsonb default null
|
|
,OUT p_retval integer
|
|
,OUT p_errmsg text
|
|
)
|
|
LANGUAGE plpgsql VOLATILE
|
|
SECURITY DEFINER
|
|
AS
|
|
$$
|
|
DECLARE
|
|
--Error Handling--
|
|
m_funcname text = 'meta.migration_run';
|
|
m_errmsg text;
|
|
m_errcontext text;
|
|
m_errdetail text;
|
|
m_errhint text;
|
|
m_errstate text;
|
|
m_retval integer;
|
|
--Error Handling--
|
|
m_dblink_conn TEXT;
|
|
m_dblink_login TEXT;
|
|
m_gotemplate text;
|
|
m_pid integer;
|
|
r_lp record;
|
|
m_errcnt integer;
|
|
G_BREAK_ERR_CNT constant integer = 500;
|
|
BEGIN
|
|
m_dblink_conn = 'dblink_migration';
|
|
p_retval = 0;
|
|
p_errmsg = '';
|
|
m_pid = pg_backend_pid();
|
|
p_info = jsonb_build_array();
|
|
|
|
m_gotemplate = $CQl$do $OUTERDO$
|
|
declare
|
|
m_lock_timeout text = '1500ms';
|
|
m_max_attempts int = 2;
|
|
m_ddl_completed boolean = false;
|
|
begin
|
|
set local lock_timeout = '1500ms';
|
|
perform set_config('lock_timeout', m_lock_timeout, false);
|
|
|
|
for i in 1..m_max_attempts loop
|
|
begin
|
|
execute $EXECMIGRATION$[proc]$EXECMIGRATION$;
|
|
m_ddl_completed = true;
|
|
exit;
|
|
exception when lock_not_available then
|
|
raise warning 'attempt %/% to lock table "test" failed', i, m_max_attempts;
|
|
|
|
perform pg_sleep(0.1);
|
|
end;
|
|
-- if i > 1
|
|
-- then
|
|
-- SET statement_timeout = 20000;
|
|
-- end if;
|
|
end loop;
|
|
end
|
|
$OUTERDO$;
|
|
$CQl$;
|
|
|
|
|
|
select 'host=127.0.0.1 dbname='||r.dbname||' port=' || r.port || ' user='|| r.loginuser ||' password=' || r.password
|
|
from f_get_local_conn('migration') r
|
|
into m_dblink_login;
|
|
|
|
if not exists (SELECT T.text from unnest(dblink_get_connections()) T where T.text = m_dblink_conn)
|
|
then
|
|
PERFORM dblink_connect(m_dblink_conn, m_dblink_login);
|
|
end if;
|
|
|
|
perform log_event(m_funcname,format('migrations_run init [%s to %s] with connection %s',p_priority_start,p_priority_end,m_dblink_conn),bt_enum('eventlog','upgrade'));
|
|
|
|
PERFORM dblink_exec(m_dblink_conn, format($S$set application_name to 'MIGRATION:%s'; $S$, m_pid), false);
|
|
|
|
for r_lp in (
|
|
select *
|
|
,''::text as result
|
|
,clock_timestamp() as startat
|
|
|
|
from meta.migration_script s
|
|
where coalesce(s.status,0) = 0
|
|
and s.priority >= p_priority_start
|
|
and s.priority <= p_priority_end
|
|
and octet_length(s.body) > 1
|
|
order by s.priority, s.sequence, s.id_migration_script
|
|
)
|
|
loop
|
|
if m_errcnt > G_BREAK_ERR_CNT
|
|
then
|
|
perform log_event(m_funcname,format('migrations_run Max Error Count [%s to %s] Errors %s/s%',p_priority_start,p_priority_end,m_errcnt,G_BREAK_ERR_CNT),bt_enum('eventlog','upgrade'));
|
|
|
|
exit;
|
|
end if;
|
|
|
|
perform dblink_exec(m_dblink_conn, format($Q$ DO $OUTERDO$ BEGIN
|
|
|
|
if not meta.f_can_migrate()
|
|
then
|
|
raise exception 'Cannot migrate. Check the f_can_migrate function.';
|
|
end if;
|
|
|
|
update meta.migration_script u
|
|
set status = 1
|
|
,changedat = now()
|
|
where u.id_migration_script = %1$s;
|
|
|
|
END; $OUTERDO$; $Q$, r_lp.id_migration_script), true)
|
|
;
|
|
|
|
begin
|
|
|
|
--raise notice 'Lp %: %',r_lp.objectname, r_lp.result;
|
|
|
|
--raise notice 'Executing % % [%,%]', r_lp.objectname , r_lp.objecttype, r_lp.priority, r_lp.sequence;
|
|
|
|
select dblink_exec(m_dblink_conn, replace(replace(replace(m_gotemplate,'[proc]', r_lp.body),'[objectname]',r_lp.objectname),'[priority]',r_lp.priority::text), true)
|
|
into r_lp.result;
|
|
|
|
r_lp.duration = clock_timestamp() - r_lp.startat;
|
|
|
|
perform log_event(m_funcname,format('Ran Script %s @%s ',r_lp.objectname,r_lp.priority),bt_enum('eventlog','upgrade'));
|
|
|
|
|
|
perform dblink_exec(m_dblink_conn, format($Q$
|
|
update meta.migration_script u
|
|
set status = 2
|
|
,changedat = now()
|
|
,duration = %2$s::interval
|
|
where u.id_migration_script = %1$s;
|
|
$Q$, r_lp.id_migration_script, quote_literal( r_lp.duration)), true)
|
|
;
|
|
|
|
p_info = jsonb_concat(p_info, jsonb_build_object('objectname',r_lp.objectname,'objecttype', r_lp.objecttype,'status','success'));
|
|
|
|
|
|
EXCEPTION
|
|
WHEN others THEN
|
|
GET STACKED DIAGNOSTICS
|
|
m_errmsg = MESSAGE_TEXT;
|
|
|
|
raise notice 'Exception % -> %',r_lp.objectname, m_errmsg;
|
|
r_lp.duration = clock_timestamp() - r_lp.startat;
|
|
perform log_event(m_funcname,format('migrations_run error %s -> %s >> %s',r_lp.objecttype,r_lp.objectname,m_errmsg),bt_enum('eventlog','local error'));
|
|
|
|
perform dblink_exec(m_dblink_conn, format($Q$
|
|
update meta.migration_script u
|
|
set status = 3
|
|
,error = %2$s || E' \nResult: ' || %3$s
|
|
,changedat = now()
|
|
,duration = %4$s::interval
|
|
where u.id_migration_script = %1$s;
|
|
$Q$, r_lp.id_migration_script, quote_literal(m_errmsg), quote_literal(coalesce(r_lp.result,'')), quote_literal( r_lp.duration) ), false);
|
|
|
|
p_info = jsonb_concat(p_info, jsonb_build_object('objectname',r_lp.objectname,'objecttype', r_lp.objecttype,'status','error', 'error',m_errmsg));
|
|
|
|
m_errcnt = coalesce(m_errcnt,0) + 1;
|
|
|
|
end;
|
|
|
|
perform dblink_exec(m_dblink_conn, format($Q$DO $DDD$
|
|
declare
|
|
m_text text;
|
|
begin
|
|
select pg_notify('upgrade.events', json_build_object('type','upgrade','status',m.status,'objecttype', m.objecttype,'objectname',m.objectname)::text)
|
|
from meta.migration_script m
|
|
where m.id_migration_script = %1$s
|
|
into m_text;
|
|
end;
|
|
$DDD$;$Q$, r_lp.id_migration_script, quote_literal(m_errmsg), quote_literal(coalesce(r_lp.result,'')) ), false);
|
|
|
|
end loop;
|
|
|
|
perform dblink_disconnect(m_dblink_conn);
|
|
|
|
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_retval = 1;
|
|
p_errmsg = format('%s Context %s State: %s', m_errmsg, m_errcontext, m_errstate);
|
|
|
|
if exists (SELECT T.text from unnest(dblink_get_connections()) T where T.text = m_dblink_conn)
|
|
then
|
|
perform dblink_disconnect(m_dblink_conn);
|
|
end if;
|
|
|
|
perform pg_notify('upgrade.events', json_build_object('type','upgrade','status',3,'error',m_errmsg,'objecttype',m_funcname)::text);
|
|
END;
|
|
$$; |