-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathkanboard-sqlite2mysql.sh
executable file
·283 lines (254 loc) · 8.69 KB
/
kanboard-sqlite2mysql.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#!/usr/bin/env bash
readonly PROGNAME=$(basename $0)
readonly PROGDIR=$(readlink -m $(dirname $0))
readonly ARGS="$@"
usage()
{
cat <<- EOF
usage: $PROGNAME <Kanboard instance physical path> [ <MySQL DB name> -h <MySQL DB host> -u <MySQL DB user> -p ] [ --help ]
-p, --password MySQL database password. If password is not given it's asked from the tty.
-h, --host MySQL database host
-u, --user MySQL database user for login
-o, --output Path to the output SQL dump compatible with MySQL
-v, --verbose Enable more verbosity
-H, --help Display this help
-V, --version Display the Kanboard SQLite2MySQL version
Example:
$PROGNAME /usr/local/share/www/kanboard -o db-mysql.sql
$PROGNAME /usr/local/share/www/kanboard kanboard -u root --password root
EOF
}
version()
{
cat <<- EOF
Kanboard SQLite2MySQL 1.1.2
Migrate your SQLite Kanboard database to MySQL in one go! By Olivier.
EOF
}
cmdline()
{
KANBOARD_PATH=
DB_HOSTNAME=
DB_USERNAME=
DB_PASSWORD=
DB_NAME=
OUTPUT_FILE=db-mysql.sql
IS_VERBOSE=0
if [ "$#" -lt "1" ]; then
echo 'error: missing arguments'
usage
exit -1
fi
while [ "$1" != "" ]; do
case $1 in
-o | --output )
shift
OUTPUT_FILE=$1
shift
;;
-h | --host )
shift
DB_HOSTNAME=$1
shift
;;
-u | --user )
shift
DB_USERNAME=$1
shift
;;
-p )
shift
echo 'Enter password: '
read DB_PASSWORD
;;
--password )
shift
DB_PASSWORD=$1
shift
;;
-v | --verbose )
shift
IS_VERBOSE=1
;;
-H | --help )
usage
exit 0
;;
-V | --version )
version
exit 0
;;
*)
if [ "${KANBOARD_PATH}" == "" ]; then
if [ ! -d "$1" ]; then
echo "error: unknown path '$1'"
usage
exit -1
fi
KANBOARD_PATH=$1
shift
elif [ "$DB_NAME" == "" ]; then
DB_NAME=$1
shift
else
echo "error: unknwon argument '$1'"
usage
exit -1
fi
;;
esac
done
if [ ! "${DB_NAME}" == "" ]; then
if [ "${DB_USERNAME}" == "" ]; then
DB_USERNAME=root
fi
if [ "${DB_HOSTNAME}" == "" ]; then
DB_HOSTNAME=localhost
fi
fi
return 0
}
# List tables names of a SQLite database
# 'sqlite3 db.sqlite .tables' already return tables names but only in column mode...
# * @param Database file
sqlite_tables()
{
local sqliteDbFile=$1
sqlite3 ${sqliteDbFile} .schema \
| sed -e '/[^C(]$/d' -e '/^\s\+($/d' -e 's/CREATE TABLE \([a-z_]*\).*/\1/' -e '/^$/d'
}
# List column names of a SQLite table
# * @param Database file
# * @param Table name
sqlite_columns()
{
local sqliteDbFile=$1
local table=$2
sqlite3 -csv -header ${sqliteDbFile} "select * from ${table};" \
| head -n 1 \
| sed -e 's/,/`,`/g' -e 's/^/`/' -e 's/$/`/'
}
# Generate "INSERT INTO" queries to dump data of an SQLite table
# * @param Database file
# * @param Table name
sqlite_dump_table_data()
{
local sqliteDbFile=$1
local table=$2
local columns=`sqlite_columns ${sqliteDbFile} ${table}`
echo -e ".mode insert ${table}\nselect * from ${table};" \
| sqlite3 ${sqliteDbFile} \
| sed -e "s/INSERT INTO \([a-z_\"]*\)/INSERT INTO \1 (${columns})/"
}
# If verbose, displays version of the schema found in the SQLite file. Beware this version is different from MySQL schema versions
sqlite_dump_schemaversion()
{
local sqliteDbFile=$1
if [ "1" == "${IS_VERBOSE}" ]; then
echo "# Found schema version `sqlite3 ${sqliteDbFile} 'PRAGMA user_version'` for SQLite"
fi
}
# Generate "INSERT INTO" queries to dump data of a SQLite database
# * @param Database file
sqlite_dump_data()
{
local sqliteDbFile=$1
local prioritizedTables='plugin_schema_versions projects columns links groups users tasks task_has_links task_has_files subtasks comments actions'
for t in $prioritizedTables; do
# Please do not ask why: this TRUNCATE is already done elsewhere, but this table "plugin_schema_versions" seems to be refillld I don't know where... This fix the issue
if [ "plugin_schema_versions" == "${t}" ]; then
echo 'TRUNCATE TABLE plugin_schema_versions;'
fi
sqlite_dump_table_data ${sqliteDbFile} ${t}
done
for t in $(sqlite_tables ${sqliteDbFile} | sed -e '/^plugin_schema_versions$/d' -e '/^projects$/d' -e '/^columns$/d' -e '/^links$/d' -e '/^groups$/d' -e '/^users$/d' -e '/^tasks$/d' -e '/^task_has_links$/d' -e '/^task_has_files$/d' -e '/^subtasks$/d' -e '/^comments$/d' -e '/^actions$/d'); do
sqlite_dump_table_data ${sqliteDbFile} ${t}
done
}
createMysqlDump()
{
local sqliteDbFile=$1
echo 'ALTER TABLE users ADD COLUMN is_admin INT DEFAULT 0;
ALTER TABLE users ADD COLUMN default_project_id INT DEFAULT 0;
ALTER TABLE users ADD COLUMN is_project_admin INT DEFAULT 0;
ALTER TABLE tasks ADD COLUMN estimate_duration VARCHAR(255) DEFAULT "";
ALTER TABLE tasks ADD COLUMN actual_duration VARCHAR(255) DEFAULT "";
ALTER TABLE project_has_users ADD COLUMN id INT DEFAULT 0;
ALTER TABLE project_has_users ADD COLUMN is_owner INT DEFAULT 0;
ALTER TABLE projects ADD COLUMN is_everybody_allowed TINYINT(1) DEFAULT 0;
ALTER TABLE projects ADD COLUMN default_swimlane VARCHAR(200) DEFAULT "Default swimlane";
ALTER TABLE projects ADD COLUMN show_default_swimlane INT DEFAULT 1;
ALTER TABLE tasks DROP FOREIGN KEY tasks_swimlane_ibfk_1;
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE settings;
TRUNCATE TABLE users;
TRUNCATE TABLE links;
TRUNCATE TABLE plugin_schema_versions;
SET FOREIGN_KEY_CHECKS = 1;' > ${OUTPUT_FILE}
echo 'ALTER TABLE `tasks` CHANGE `column_id` `column_id` INT( 11 ) NULL;' >> ${OUTPUT_FILE}
sqlite_dump_data ${sqliteDbFile} >> ${OUTPUT_FILE}
echo 'ALTER TABLE users DROP COLUMN is_admin;
ALTER TABLE users DROP COLUMN default_project_id;
ALTER TABLE users DROP COLUMN is_project_admin;
ALTER TABLE tasks DROP COLUMN estimate_duration;
ALTER TABLE tasks DROP COLUMN actual_duration;
ALTER TABLE project_has_users DROP COLUMN id;
ALTER TABLE project_has_users DROP COLUMN is_owner;
ALTER TABLE projects DROP COLUMN is_everybody_allowed;
ALTER TABLE projects DROP COLUMN default_swimlane;
ALTER TABLE projects DROP COLUMN show_default_swimlane;' >> ${OUTPUT_FILE}
#echo 'ALTER TABLE `tasks` CHANGE `column_id` `column_id` INT( 11 ) NOT NULL;' >> ${OUTPUT_FILE}
echo 'ALTER TABLE tasks ADD CONSTRAINT tasks_swimlane_ibfk_1 FOREIGN KEY (swimlane_id) REFERENCES swimlanes(id) ON DELETE CASCADE;' >> ${OUTPUT_FILE}
# For MySQL, we need to double the anti-slash (\\ instead of \)
# But we need to take care of Windows URL (e.g. C:\test\) in the JSON of project_activities (e.g. C:\test\" shall not become C:\\test\\" this will break the json...). Windows URL are transformed into Linux URL for this reason
cat ${OUTPUT_FILE} \
| sed -e 's/\\\\"/"/g' \
| sed -e 's/\\\\/\//g' \
| sed -e 's/\\"/##"/g' \
| sed -e 's/\\u\([[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]\)/##u\1/g' \
| sed -e 's/\\/\//g' \
| sed -e 's/##"/\\\\"/g' \
| sed -e 's/##u\([[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]\)/\\u\1/g' \
| sed -e 's/\/Kanboard\/Action\//\\\\Kanboard\\\\Action\\\\/g' \
| sed -e 's/\/r\/n/\\\\n/g' \
| sed -e 's/\/\//\//g' \
> db.mysql
mv db.mysql ${OUTPUT_FILE}
}
generateMysqlSchema()
{
mv ${KANBOARD_PATH}/config.php ${KANBOARD_PATH}/config_tmp.php
export DATABASE_URL="mysql://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOSTNAME}/${DB_NAME}"
php ${KANBOARD_PATH}/app/common.php
mv ${KANBOARD_PATH}/config_tmp.php ${KANBOARD_PATH}/config.php
}
fillMysqlDb()
{
local verbosity=
if [ "1" == "${IS_VERBOSE}" ]; then
verbosity="--verbose"
fi
mysql ${verbosity} -h ${DB_HOSTNAME} -u ${DB_USERNAME} --password=${DB_PASSWORD} ${DB_NAME} \
< ${OUTPUT_FILE}
}
main()
{
cmdline $ARGS
local sqliteDbFile=${KANBOARD_PATH}/data/db.sqlite
sqlite_dump_schemaversion ${sqliteDbFile}
echo '# Create MySQL data dump from SQLite database'
createMysqlDump ${sqliteDbFile} \
&& (echo "done" ; echo "check ${OUTPUT_FILE}") \
|| (echo 'FAILLURE' ; exit -1)
if [ ! "${DB_NAME}" == "" ]; then
echo '# Generate schema in the MySQL database using Kanboard'
generateMysqlSchema \
&& echo "done" \
|| (echo 'FAILLURE' ; exit -1)
echo '# Fill the MySQL database with the SQLite database data'
fillMysqlDb \
&& echo "done" \
|| (echo 'FAILLURE' ; exit -1)
fi
}
main