表題のママ。
開発用のWikiで集積してたデータを運用用のプロジェクト内に移動したいみたいな話。
redmineのDBを直接読み書きできる人向け。
雑に作ってるので流す前にバックアップ必須。
Copy Wiki to another project - Redmine でアップロードされているSQLでだいたい解決するものの、
- Wikiページに添付されたファイルが複製されない
- パラメータが
wiki_id
になっているのがちょっと微妙
というのがあって修正した。
redmineのdatabase
だいたいこんな構造になってる。
plantumlソース
@startuml
class attachments{
int id
int content_id
int content_type
}
class projects{
int id
}
class wikis{
int id
int project_id
}
class wiki_contents
class wiki_content_versions{
int wiki_content_id
}
class wiki_pages{
int id
int wiki_id
}
class wiki_redirects
projects -left- wikis : projects.id=wikis.project_id
wikis *-- wiki_pages
wikis *-left- wiki_redirects
wiki_pages --- wiki_contents : id
wiki_contents *-right- wiki_content_versions
wiki_pages *-right- attachments : attachments.container_type='WikiPage'\nattachments.container_id=wiki_pages.id
@enduml
まずはプロジェクトidを調べる
redmineのDBのprojects.id
を使ってコピー元、コピー先のidを調べておく。
コピー用プロシージャを登録
以下のreplicawiki2.sqlをローカルに保存して
$ mysql -p <redmine_database> < replicawiki2.sql
で登録する。
注意:コピー先にWikiページが存在する場合一度削除されます。
replicawiki2.sql
delimiter //
drop procedure if exists replicawiki2;
create procedure replicawiki2(projectid_from int, projectid_to int)
begin
declare done int default 0;
declare last_id int;
declare st_page varchar(255);
declare curso int;
declare id_or int;
declare id_nu int;
declare wikid_from int;
declare wikid_to int
declare pages cursor for select id from wiki_pages wp where wp.wiki_id = wikid_from;
declare copied_pages cursor for select id_original, id_new from aux_map;
declare continue handler for not found set done = 1;
-- get wiki id
select wikis.id into wikid_from from wikis where wikis.project_id = projectid_from;
select wikis.id into wikid_to from wikis where wikis.project_id = projectid_to;
-- caution this erase all current wiki pages of destination (to) wiki
delete from attachments where container_type='wikipages' and container_id in (select id from wiki_pages where wiki_pages.wiki_id = wikid_to);
delete from wiki_contents where id in (select id from wiki_pages where wiki_pages.wiki_id = wikid_to);
delete from wiki_redirects where wiki_id = wikid_to ;
delete from wiki_pages where wiki_pages.wiki_id = wikid_to ;
open pages;
-- fix wikis start page
select wikis.start_page into st_page from wikis where id = wikid_from;
update wikis set start_page = st_page where id = wikid_to;
-- aux table to replicate the hierachy
drop table if exists aux_map;
create table aux_map(id_original int, id_new int);
-- copy redirects
insert into wiki_redirects (wiki_id, `title`, redirects_to, created_on,redirects_to_wiki_id)
select wikid_to as wiki_id, `title`, redirects_to, created_on ,wiki_to as redirects_to_wiki_id from wiki_redirects where wiki_id = wikid_from;
-- copy all the wiki pages to origin to dest. and fill the auxiliary hierachy table
repeat
fetch pages into curso;
insert into wiki_pages (wiki_id, title, created_on, protected, parent_id)
select wikid_to as wiki_id, wp.title, wp.created_on, wp.protected, wp.parent_id from wiki_pages wp where wp.id = curso limit 1;
set last_id = last_insert_id();
insert into aux_map (id_original, id_new)
values(curso, last_id);
until done end repeat;
set done = 0;
open copied_pages;
-- update hierachy and copy all the wiki contents.
repeat
fetch copied_pages into id_or, id_nu;
update wiki_pages set parent_id = id_nu where wiki_id = wikid_to and parent_id = id_or;
insert into wiki_contents (page_id, author_id, `text`, `comments`, `updated_on`, `version`)
select id_nu as page_id, author_id, `text`, `comments`, `updated_on`, `version` from wiki_contents wc where wc.page_id = id_or;
until done end repeat;
-- clone attachments
insert into attachments(container_id,container_type,filename,disk_filename,filesize,content_type,digest,downloads,author_id,created_on,description,disk_directory)
select
aux_map.id_new,
container_type,
filename,
concat('c',disk_filename),
filesize,
content_type,
digest,
downloads,
author_id,
created_on,
description,
disk_directory
from `attachments`
inner join aux_map on attachments.container_id = id_original
where container_type='wikipage' ;
-- print cannonical attachment copy script
select
concat('cp -n ',disk_directory ,'/', disk_filename,' ',disk_directory ,'/c', disk_filename,' ;') as pathto
from `attachments`
inner join aux_map on attachments.container_id = id_original
where container_type='wikipage' ;
close pages;
close copied_pages;
-- deleting auxiliary table
drop table if exists aux_map;
end
//
実行
call replicawiki2(1,2); -- project_id=1から2へWikiの内容をコピー
これを実行するとコンソールに物理ファイルコピー用のコマンドが出力される
出力結果
cp -n 2021/03/150222162940_fb8abc027e5f98ab48c8b90bd550507d.png 2021/03/c150222162940_fb8abc027e5f98ab48c8b90bd550507d.png ;
cp -n 2021/03/150312113518_f257bd912a377aea98b7550787460168.png 2021/03/c150312113518_f257bd912a377aea98b7550787460168.png ;
# : 以下略
<redmine_home>/files
で↑のコマンドを実行すればOK