select * from dropall('migration_init','meta'); CREATE OR REPLACE FUNCTION meta.migration_init( p_version text default '' ,INOUT p_info jsonb default null ,OUT p_retval integer ,OUT p_errmsg text ) LANGUAGE plpgsql VOLATILE SECURITY DEFINER AS $$ DECLARE m_except _except_type; m_dblink_conn TEXT; m_dblink_login TEXT; m_pid integer; m_result text; m_gotemplate text; m_qry text; m_id_model integer; BEGIN m_except.func_name = 'migration_init'; p_retval = 0; p_errmsg = ''; m_dblink_conn := 'dblink_migration_boot'; m_pid = pg_backend_pid(); perform pg_notify('upgrade.events', json_build_object('type','upgrade','status',1,'objecttype',m_except.func_name, 'tm',clock_timestamp()::text)::text); if p_info is null then p_info = jsonb_build_object(); end if; select f.id_migration_model from meta.migration_model f where f.version = p_version or coalesce(p_version,'') = '' order by f.changedat desc limit 1 into m_id_model; if coalesce(m_id_model,0) = 0 then raise exception 'Model/File does not exist for version %',p_version; end if; -- delete from meta.migration_script s -- where s.rid_migration_model = m_id_model or s.rid_migration_model is null; -- -- delete from meta.migration_relation s -- where s.rid_migration_model = m_id_model or s.rid_migration_model is null; -- -- delete from meta.migration_index s -- where s.rid_migration_model = m_id_model or s.rid_migration_model is null; -- -- delete from meta.migration_table s -- where s.rid_migration_model = m_id_model or s.rid_migration_model is null; m_gotemplate = $CQl$do $M$ declare m_retval integer; m_errmsg text; m_info jsonb; m_file bytea; m_version text; m_rid_model integer; begin m_version = $CQl$ || quote_literal(p_version) || $CQl$; m_rid_model = $CQl$ ||m_id_model || $CQl$; perform log_event($CQl$ || quote_literal(m_except.func_name) || $CQl$ ,'[message]',bt_enum('eventlog','upgrade'),1); [proc] end; $M$; $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_except.func_name,format('migrations init with connection %s',m_dblink_conn),bt_enum('eventlog','upgrade')); PERFORM dblink_exec(m_dblink_conn, format($S$set application_name to 'MIGRATION:%s'; $S$, m_pid), true); m_qry = replace(replace(m_gotemplate,'[message]','Reading migration models'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_read(m_rid_model) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to read model: %', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); -- raise notice 'Status - Reading migration models: % Qry:%', m_result , m_qry; ---Prime old upgrades m_qry = replace(replace(m_gotemplate,'[message]','Inspecting database'),'[proc]',$CQl$ if exists ( select 1 from information_schema.tables t where t.table_name = 'upgrades' and t.table_schema = 'public' ) then insert into public.upgrades(dbversion,status) select m.version, 0 from meta.migration_model m where m.id_migration_model = m_rid_model and not exists (select 1 from public.upgrades s2 where s2.dbversion = m.version) ; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); --inspect m_qry = replace(replace(m_gotemplate,'[message]','Inspecting database'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_inspect(m_rid_model,$CQl$ || quote_literal(p_info::text) || $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to inspect database: %', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); -- raise notice 'Status - Inspecting database: % Qry:%', m_result, m_qry; --Drops m_qry = replace(replace(m_gotemplate,'[message]','Build Differential (Drops)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_build(m_rid_model,'drop',$CQl$ || quote_literal(p_info::text)|| $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to build differential: % ', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); --Run Drops m_qry = replace(replace(m_gotemplate,'[message]','Running Migration Scripts (Drops)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_run(m_rid_model,0,200,$CQl$ || quote_literal(p_info::text)|| $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to run differentials: %', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); --Renames m_qry = replace(replace(m_gotemplate,'[message]','Inspecting database (Renames)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_inspect(m_rid_model,$CQl$ || quote_literal(p_info::text) || $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to inspect database: %', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); -- raise notice 'Status - Inspecting database: % Qry:%', m_result, m_qry; --Run rename m_qry = replace(replace(m_gotemplate,'[message]','Build Differential (Renames)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_build(m_rid_model,'rename',$CQl$ || quote_literal(p_info::text)|| $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to build differential: % ', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); --Functions m_qry = replace(replace(m_gotemplate,'[message]','Build Differential (Renames)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_build(m_rid_model,'functions',$CQl$ || quote_literal(p_info::text)|| $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to build differential: % ', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); m_qry = replace(replace(m_gotemplate,'[message]','Update legacy'),'[proc]',$CQl$ if exists ( select 1 from information_schema.tables t where t.table_name = 'upgrades' and t.table_schema = 'public' ) then update public.upgrades s set totalscripts = r.total ,failedscripts = r.error ,scriptsdone = r.done from ( select count(1) filter (where s.status <> 4) as total , count(1) filter (where s.status = 3) as error , count(1) filter (where s.status = 2 ) as done from meta.migration_script s where s.rid_migration_model = m_rid_model ) r where s.dbversion in (select m.version from meta.migration_model m where m.id_migration_model = m_rid_model ); end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); --Run Functions m_qry = replace(replace(m_gotemplate,'[message]','Running Migration Scripts (Renames)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_run(m_rid_model,0,200,$CQl$ || quote_literal(p_info::text)|| $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to run differentials: %', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); ---Rest m_qry = replace(replace(m_gotemplate,'[message]','Inspecting database (2nd)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_inspect(m_rid_model,$CQl$ || quote_literal(p_info::text) || $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to inspect database: %', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); -- Rest m_qry = replace(replace(m_gotemplate,'[message]','Build Differential (All)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_build(m_rid_model,'all',$CQl$ || quote_literal(p_info::text)|| $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to build differential: % ', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); -- Run Rest m_qry = replace(replace(m_gotemplate,'[message]','Running Migration Scripts (2nd)'),'[proc]',$CQl$ select r.p_retval, r.p_errmsg, r.p_info from meta.migration_run(m_rid_model,0,10000,$CQl$ || quote_literal(p_info::text)|| $CQl$::jsonb) r into m_retval, m_errmsg,m_info; if m_retval > 0 then raise exception 'Failed to run differentials: %', m_errmsg; end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); m_qry = replace(replace(m_gotemplate,'[message]','Update legacy'),'[proc]',$CQl$ if exists ( select 1 from information_schema.tables t where t.table_name = 'upgrades' and t.table_schema = 'public' ) then update public.upgrades s set totalscripts = r.total ,failedscripts = r.error ,scriptsdone = r.done from ( select count(1) filter (where s.status <> 4) as total , count(1) filter (where s.status = 3) as error , count(1) filter (where s.status = 2 ) as done from meta.migration_script s where s.rid_migration_model = m_rid_model ) r where s.dbversion in (select m.version from meta.migration_model m where m.id_migration_model = m_rid_model ); end if; $CQl$); m_result = dblink_exec(m_dblink_conn, m_qry, true); --raise notice 'Status - Running Migration Scripts: % Qry:%', m_result, m_qry; perform dblink_disconnect(m_dblink_conn); perform log_event(m_except.func_name,'Migration process completed. Check the scripts status for errors',bt_enum('eventlog','upgrade')); perform pg_notify('upgrade.events', json_build_object('type','upgrade','status',2,'objecttype',m_except.func_name, 'tm',clock_timestamp()::text)::text); EXCEPTION WHEN others THEN GET STACKED DIAGNOSTICS m_except.message_text = MESSAGE_TEXT , m_except.pg_exception_context = PG_EXCEPTION_CONTEXT , m_except.pg_exception_detail = PG_EXCEPTION_DETAIL , m_except.pg_exception_hint = PG_EXCEPTION_HINT , m_except.returned_sqlstate = RETURNED_SQLSTATE , m_except.schema_name = SCHEMA_NAME , m_except.table_name = TABLE_NAME , m_except.pg_datatype_name = PG_DATATYPE_NAME , m_except.constraint_name = CONSTRAINT_NAME , m_except.column_name = COLUMN_NAME ; p_errmsg = _except(m_except); p_retval = 1; perform log_event(m_except.func_name,format('Migration error: %s',p_errmsg),bt_enum('eventlog','upgrade')); 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',p_errmsg,'objecttype',m_except.func_name, 'tm',clock_timestamp()::text)::text); END; $$;