-
Notifications
You must be signed in to change notification settings - Fork 0
/
ss14_sqlite_to_postgres.pgloader
281 lines (230 loc) · 14.1 KB
/
ss14_sqlite_to_postgres.pgloader
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
-- Before running this, you have to do this query on the source sqlite database:
-- `UPDATE profile SET markings = CAST(markings AS TEXT);`
-- This fixes copying the json over, because jsonb is a different format entirely in sqlite.
-- Note that you can write pgloader scripts to run queries on the target database before starting,
-- but not to run queries on the source database, so you have to do this manually.
-- You can also truncate admin_log and admin_log_player in the sqlite,
-- since they make up 99% of the data so you'll save a lot of time,
-- and long log messages can cause a weird error with
-- "word is too long to be indexed"
-- which I haven't been able to figure out.
-- `DELETE FROM admin_log; DELETE FROM admin_log_player;`
-- references:
-- https://pgloader.readthedocs.io/en/latest/ref/sqlite.html
-- https://pgloader.readthedocs.io/en/latest/command.html
-- https://www.sqlite.org/datatype3.html
-- https://www.postgresql.org/docs/current/datatype.html
LOAD DATABASE
FROM {{SQLITEPATH}}
INTO {{POSTGRESPATH}}
WITH
-- don't drop or create tables, the server application creates them first
include no drop, create no tables,
create no indexes, no foreign keys,
-- remove any rows created by running the server application
truncate,
-- disables foreign key checking while loading the data,
-- then re-enables it afterwards.
-- enables data to be loaded into tables with
-- pre-existing constraints not created by pgloader
disable triggers,
-- set postgres sequences to appropriate ids
-- this actually doesn't work because pgloader only
-- does this for sequences it creates.
-- so we do this manually with AFTER LOAD DO
-- reset sequences,
-- this seems to fix a "heap exhausted" error
-- see here https://github.com/dimitri/pgloader/issues/962#issuecomment-490258129
-- default 100000
prefetch rows = 25000
-- sqlite types all bogstandard INTEGER, TEXT
-- BLOBS all go to bytea, default pgloader casting
-- only notable sqlite types:
-- preference.admin_ooc_color is lowercase "text"
-- admin_log.json and profile.markings are "jsonb"
-- columns named "id" are either INTEGER or TEXT uuids
-- INTEGERs are going to integer not the default bigint
-- so I would change the default type cast and cast columns that are exceptions
-- I don't know why someone suggested casting integer ids to serials
-- when they're integers with generated by default as identity
-- I have put that in but left it commented out for now
-- tables are alphabetic
-- columns within tables are in the order shown by pgAdmin 4
CAST
column admin.user_id to uuid,
-- column admin_flag.admin_flag_id to serial,
column admin_flag.admin_flag_id to integer,
column admin_flag.negative to boolean,
column admin_flag.admin_id to uuid,
column admin_log.date to timestamptz using sqlite-timestamp-to-timestamp,
-- column admin_log.json to jsonb,
column admin_log.impact to smallint,
column admin_log_player.player_user_id to uuid,
-- column admin_messages.admin_messages_id to serial,
column admin_messages.admin_messages_id to integer,
column admin_messages.player_user_id to uuid,
column admin_messages.playtime_at_note to interval,
column admin_messages.message to varchar,
column admin_messages.created_by_id to uuid,
column admin_messages.created_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_messages.last_edited_by_id to uuid,
column admin_messages.last_edited_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_messages.expiration_time to timestamptz using sqlite-timestamp-to-timestamp,
column admin_messages.deleted to boolean,
column admin_messages.deleted_by_id to uuid,
column admin_messages.deleted_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_messages.seen to boolean,
column admin_messages.dismissed to boolean,
-- column admin_notes.admin_notes_id to serial,
column admin_notes.admin_notes_id to integer,
column admin_notes.player_user_id to uuid,
column admin_notes.message to varchar,
column admin_notes.created_by_id to uuid,
column admin_notes.created_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_notes.last_edited_by_id to uuid,
column admin_notes.last_edited_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_notes.deleted to boolean,
column admin_notes.deleted_by_id to uuid,
column admin_notes.deleted_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_notes.secret to boolean,
column admin_notes.expiration_time to timestamptz using sqlite-timestamp-to-timestamp,
column admin_notes.playtime_at_note to interval,
-- column admin_rank.admin_rank_id to serial,
column admin_rank.admin_rank_id to integer,
-- column admin_rank_flag.admin_rank_flag_id to serial,
column admin_rank_flag.admin_rank_flag_id to integer,
-- column admin_watchlists.admin_watchlists_id to serial,
column admin_watchlists.admin_watchlists_id to integer,
column admin_watchlists.player_user_id to uuid,
column admin_watchlists.playtime_at_note to interval,
column admin_watchlists.message to varchar,
column admin_watchlists.created_by_id to uuid,
column admin_watchlists.created_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_watchlists.last_edited_by_id to uuid,
column admin_watchlists.last_edited_at to timestamptz using sqlite-timestamp-to-timestamp,
column admin_watchlists.expiration_time to timestamptz using sqlite-timestamp-to-timestamp,
column admin_watchlists.deleted to boolean,
column admin_watchlists.deleted_by_id to uuid,
column admin_watchlists.deleted_at to timestamptz using sqlite-timestamp-to-timestamp,
-- column antag.antag_id to serial,
column antag.antag_id to integer,
-- column assigned_user_id.assigned_user_id_id to serial,
column assigned_user_id.assigned_user_id_id to integer,
column assigned_user_id.user_id to uuid,
column ban_template.length to interval,
column ban_template.auto_delete to boolean,
column ban_template.hidden to boolean,
-- column connection_log.connection_log_id to serial,
column connection_log.connection_log_id to integer,
column connection_log.user_id to uuid,
column connection_log.time to timestamptz using sqlite-timestamp-to-timestamp,
column connection_log.address to inet,
column connection_log.denied to smallint,
-- column job.job_id to serial,
column job.job_id to integer,
-- column play_time.play_time_id to serial,
column play_time.play_time_id to integer,
column play_time.player_id to uuid,
column play_time.time_spent to interval,
-- column player.player_id to serial,
column player.player_id to integer,
column player.user_id to uuid,
column player.first_seen_time to timestamptz using sqlite-timestamp-to-timestamp,
column player.last_seen_time to timestamptz using sqlite-timestamp-to-timestamp,
column player.last_seen_address to inet,
column player.last_read_rules to timestamptz using sqlite-timestamp-to-timestamp,
-- none in player_round table
-- column preference.preference_id to serial,
column preference.preference_id to integer,
column preference.user_id to uuid,
-- column profile.profile_id to serial,
column profile.profile_id to integer,
-- column profile.markings to jsonb,
-- column profile_loadout.profile_loadout_id to serial,
column profile_loadout.profile_loadout_id to integer,
-- column profile_loadout_group.profile_loadout_group_id to serial,
column profile_loadout_group.profile_loadout_group_id to integer,
-- column profile_role_loadout.profile_role_loadout_id to serial,
column profile_role_loadout.profile_role_loadout_id to integer,
column role_whitelists.player_user_id to uuid,
-- column round.round_id to serial,
column round.round_id to integer,
column round.start_date to timestamptz using sqlite-timestamp-to-timestamp,
-- column server.server_id to serial,
column server.server_id to integer,
-- column server_ban.server_ban_id to serial,
column server_ban.server_ban_id to integer,
column server_ban.player_user_id to uuid,
column server_ban.address to inet,
column server_ban.ban_time to timestamptz using sqlite-timestamp-to-timestamp,
column server_ban.expiration_time to timestamptz using sqlite-timestamp-to-timestamp,
column server_ban.banning_admin to uuid,
column server_ban.auto_delete to boolean,
column server_ban.hidden to boolean,
column server_ban.last_edited_at to timestamptz using sqlite-timestamp-to-timestamp,
column server_ban.last_edited_by_id to uuid,
column server_ban.playtime_at_note to interval,
column server_ban_exemption.user_id to uuid,
-- column server_ban_hit.server_ban_hit_id to serial,
column server_ban_hit.server_ban_hit_id to integer,
-- column server_role_ban.server_role_ban_id to serial,
column server_role_ban.server_role_ban_id to integer,
column server_role_ban.player_user_id to uuid,
column server_role_ban.address to inet,
column server_role_ban.ban_time to timestamptz using sqlite-timestamp-to-timestamp,
column server_role_ban.expiration_time to timestamptz using sqlite-timestamp-to-timestamp,
column server_role_ban.banning_admin to uuid,
column server_role_ban.hidden to boolean,
column server_role_ban.last_edited_at to timestamptz using sqlite-timestamp-to-timestamp,
column server_role_ban.last_edited_by_id to uuid,
column server_role_ban.playtime_at_note to interval,
-- column server_role_unban.role_unban_id to serial,
column server_role_unban.role_unban_id to integer,
column server_role_unban.unbanning_admin to uuid,
column server_role_unban.unban_time to timestamptz using sqlite-timestamp-to-timestamp,
-- column server_unban.unban_id to serial,
column server_unban.unban_id to integer,
column server_unban.unbanning_admin to uuid,
column server_unban.unban_time to timestamptz using sqlite-timestamp-to-timestamp,
-- column trait.trait_id to serial,
column trait.trait_id to integer,
-- column uploaded_resource_log.uploaded_resource_log_id to serial,
column uploaded_resource_log.uploaded_resource_log_id to integer,
column uploaded_resource_log.date to timestamptz using sqlite-timestamp-to-timestamp,
column uploaded_resource_log.user_id to uuid,
column whitelist.user_id to uuid,
-- "the first match prevents following rules to be applied"
-- https://pgloader.readthedocs.io/en/latest/ref/pgsql.html#postgresql-database-casting-rules
type integer to integer using integer-to-string
-- reset existing sequences
-- you can see how pgloader does it here:
-- https://github.com/dimitri/pgloader/blob/29afa9de0563b25bf2da3a9b2d84e2b1b25de098/src/pgsql/pgsql-create-schema.lisp#L381
AFTER LOAD DO
$$ SELECT setval('admin_flag_admin_flag_id_seq', (SELECT GREATEST(MAX(admin_flag_id), 1) FROM admin_flag)); $$,
$$ SELECT setval('admin_messages_admin_messages_id_seq', (SELECT GREATEST(MAX(admin_messages_id), 1) FROM admin_messages)); $$,
$$ SELECT setval('admin_notes_admin_notes_id_seq', (SELECT GREATEST(MAX(admin_notes_id), 1) FROM admin_notes)); $$,
$$ SELECT setval('admin_rank_admin_rank_id_seq', (SELECT GREATEST(MAX(admin_rank_id), 1) FROM admin_rank)); $$,
$$ SELECT setval('admin_rank_flag_admin_rank_flag_id_seq', (SELECT GREATEST(MAX(admin_rank_flag_id), 1) FROM admin_rank_flag)); $$,
$$ SELECT setval('admin_watchlists_admin_watchlists_id_seq', (SELECT GREATEST(MAX(admin_watchlists_id), 1) FROM admin_watchlists)); $$,
$$ SELECT setval('antag_antag_id_seq', (SELECT GREATEST(MAX(antag_id), 1) FROM antag)); $$,
$$ SELECT setval('assigned_user_id_assigned_user_id_id_seq', (SELECT GREATEST(MAX(assigned_user_id_id), 1) FROM assigned_user_id)); $$,
$$ SELECT setval('ban_template_ban_template_id_seq', (SELECT GREATEST(MAX(ban_template_id), 1) FROM ban_template)); $$,
$$ SELECT setval('connection_log_connection_log_id_seq', (SELECT GREATEST(MAX(connection_log_id), 1) FROM connection_log)); $$,
$$ SELECT setval('job_job_id_seq', (SELECT GREATEST(MAX(job_id), 1) FROM job)); $$,
$$ SELECT setval('play_time_play_time_id_seq', (SELECT GREATEST(MAX(play_time_id), 1) FROM play_time)); $$,
$$ SELECT setval('player_player_id_seq', (SELECT GREATEST(MAX(player_id), 1) FROM player)); $$,
$$ SELECT setval('preference_preference_id_seq', (SELECT GREATEST(MAX(preference_id), 1) FROM preference)); $$,
$$ SELECT setval('profile_loadout_group_profile_loadout_group_id_seq', (SELECT GREATEST(MAX(profile_loadout_group_id), 1) FROM profile_loadout_group)); $$,
$$ SELECT setval('profile_loadout_profile_loadout_id_seq', (SELECT GREATEST(MAX(profile_loadout_id), 1) FROM profile_loadout)); $$,
$$ SELECT setval('profile_profile_id_seq', (SELECT GREATEST(MAX(profile_id), 1) FROM profile)); $$,
$$ SELECT setval('profile_role_loadout_profile_role_loadout_id_seq', (SELECT GREATEST(MAX(profile_role_loadout_id), 1) FROM profile_role_loadout)); $$,
$$ SELECT setval('round_round_id_seq', (SELECT GREATEST(MAX(round_id), 1) FROM round)); $$,
$$ SELECT setval('server_ban_hit_server_ban_hit_id_seq', (SELECT GREATEST(MAX(server_ban_hit_id), 1) FROM server_ban_hit)); $$,
$$ SELECT setval('server_ban_server_ban_id_seq', (SELECT GREATEST(MAX(server_ban_id), 1) FROM server_ban)); $$,
$$ SELECT setval('server_role_ban_server_role_ban_id_seq', (SELECT GREATEST(MAX(server_role_ban_id), 1) FROM server_role_ban)); $$,
$$ SELECT setval('server_role_unban_role_unban_id_seq', (SELECT GREATEST(MAX(role_unban_id), 1) FROM server_role_unban)); $$,
$$ SELECT setval('server_server_id_seq', (SELECT GREATEST(MAX(server_id), 1) FROM server)); $$,
$$ SELECT setval('server_unban_unban_id_seq', (SELECT GREATEST(MAX(unban_id), 1) FROM server_unban)); $$,
$$ SELECT setval('trait_trait_id_seq', (SELECT GREATEST(MAX(trait_id), 1) FROM trait)); $$,
$$ SELECT setval('uploaded_resource_log_uploaded_resource_log_id_seq', (SELECT GREATEST(MAX(uploaded_resource_log_id), 1) FROM uploaded_resource_log)); $$
;