forked from RedGuides/MQ2LinkDB
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMQ2LinkDBTables.cpp
465 lines (446 loc) · 10.5 KB
/
MQ2LinkDBTables.cpp
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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
#include "MQ2LinkDBTables.h"
static void extract_link_data(sqlite3_context* context, int argc, sqlite3_value** argv)
{
if (argc == 2)
{
auto value = reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
auto mode = sqlite3_value_int(argv[1]);
TextTagInfo info = ExtractLink(value);
sqlite3_result_text(context, mode == 1 ? info.text.data() : info.link.data(), static_cast<int>(mode == 1 ? info.text.length(): info.link.length()), SQLITE_STATIC);
}
}
std::string MQ2LinkDBTables::getSQLCreateStmt()
{
return std::string(R"SQL(
PRAGMA journal_mode=WAL;
CREATE TABLE IF NOT EXISTS raw_item_data_315(
itemclass INT,
name TEXT,
lore TEXT,
idfile TEXT,
lorefile TEXT,
id INT PRIMARY KEY,
weight INT,
norent INT,
nodrop INT,
attuneable INT,
size INT,
slots INT,
price INT,
icon INT,
benefitflag INT,
tradeskills INT,
cr INT,
dr INT,
pr INT,
mr INT,
fr INT,
svcorruption INT,
astr INT,
asta INT,
aagi INT,
adex INT,
acha INT,
aint INT,
awis INT,
hp INT,
mana INT,
endur INT,
ac INT,
regen INT,
manaregen INT,
enduranceregen INT,
classes INT,
races INT,
deity INT,
skillmodvalue INT,
skillmodmax INT,
skillmodtype INT,
skillmodextra INT,
banedmgrace INT,
banedmgbody INT,
banedmgraceamt INT,
banedmgamt INT,
magic INT,
foodduration INT,
reqlevel INT,
reclevel INT,
recskill INT,
bardtype INT,
bardvalue INT,
unk002 INT,
unk003 INT,
unk004 INT,
light INT,
delay INT,
elemdmgtype INT,
elemdmgamt INT,
range INT,
damage INT,
color INT,
prestige INT,
unk006 INT,
unk007 INT,
unk008 INT,
itemtype INT,
material INT,
materialunk1 INT,
elitematerial INT,
heroforge1 INT,
heroforge2 INT,
sellrate INT,
extradmgskill INT,
extradmgamt INT,
charmfileid INT,
factionmod1 INT,
factionamt1 INT,
factionmod2 INT,
factionamt2 INT,
factionmod3 INT,
factionamt3 INT,
factionmod4 INT,
factionamt4 INT,
charmfile TEXT,
augtype INT,
augstricthidden INT,
augrestrict INT,
augslot1type INT,
augslot1visible INT,
augslot1unk2 INT,
augslot2type INT,
augslot2visible INT,
augslot2unk2 INT,
augslot3type INT,
augslot3visible INT,
augslot3unk2 INT,
augslot4type INT,
augslot4visible INT,
augslot4unk2 INT,
augslot5type INT,
augslot5visible INT,
augslot5unk2 INT,
augslot6type INT,
augslot6visible INT,
augslot6unk2 INT,
pointtype INT,
ldontheme INT,
ldonprice INT,
ldonsellbackrate INT,
ldonsold INT,
bagtype INT,
bagslots INT,
bagsize INT,
bagwr INT,
booktype INT,
booklang INT,
filename TEXT,
loregroup INT,
artifactflag INT,
summoned INT,
favor INT,
fvnodrop INT,
attack INT,
haste INT,
guildfavor INT,
augdistiller INT,
unk009 INT,
unk010 INT,
nopet INT,
unk011 INT,
stacksize INT,
notransfer INT,
expendablearrow INT,
unk012 INT,
unk013 INT,
clickeffect INT,
clicklevel2 INT,
clicktype INT,
clicklevel INT,
clickmaxcharges INT,
clickcasttime INT,
clickrecastdelay INT,
clickrecasttype INT,
clickunk5 INT,
clickname INT,
clickunk7 INT,
proceffect INT,
proclevel2 INT,
proctype INT,
proclevel INT,
procunk1 INT,
procunk2 INT,
procunk3 INT,
procunk4 INT,
procrate INT,
procname INT,
procunk7 INT,
worneffect INT,
wornlevel2 INT,
worntype INT,
wornlevel INT,
wornunk1 INT,
wornunk2 INT,
wornunk3 INT,
wornunk4 INT,
wornunk5 INT,
wornname INT,
wornunk7 INT,
focuseffect INT,
focuslevel2 INT,
focustype INT,
focuslevel INT,
focusunk1 INT,
focusunk2 INT,
focusunk3 INT,
focusunk4 INT,
focusunk5 INT,
focusname INT,
focusunk7 INT,
scrolleffect INT,
scrolllevel2 INT,
scrolltype INT,
scrolllevel INT,
scrollunk1 INT,
scrollunk2 INT,
scrollunk3 INT,
scrollunk4 INT,
scrollunk5 INT,
scrollname INT,
scrollunk7 INT,
bardeffect INT,
bardlevel2 INT,
bardeffecttype INT,
bardlevel INT,
bardunk1 INT,
bardunk2 INT,
bardunk3 INT,
bardunk4 INT,
bardunk5 INT,
bardname INT,
bardunk7 INT,
unk014 TEXT,
unk015 TEXT,
unk016 TEXT,
unk017 INT,
unk018 INT,
unk019 INT,
unk020 INT,
unk021 INT,
unk022 INT,
scriptfile INT,
questitemflag INT,
powersourcecapacity INT,
purity INT,
epic INT,
backstabdmg INT,
heroic_str INT,
heroic_int INT,
heroic_wis INT,
heroic_agi INT,
heroic_dex INT,
heroic_sta INT,
heroic_cha INT,
unk029 INT,
healamt INT,
spelldmg INT,
clairvoyance INT,
unk030 INT,
unk031 INT,
unk032 INT,
unk033 INT,
unk034 INT,
unk035 INT,
unk036 INT,
unk037 INT,
heirloom INT,
placeable INT,
unk038 INT,
unk039 INT,
unk040 INT,
unk041 INT,
unk042 INT,
unk043 INT,
unk044 INT,
placeablenpcname TEXT,
unk046 INT,
unk047 INT,
unk048 INT,
unk049 INT,
unk050 INT,
unk051 INT,
unk052 INT,
unk053 INT,
unk054 INT,
unk055 INT,
unk056 INT,
unk057 INT,
unk058 INT,
unk059 INT,
unk060 INT,
unk061 INT,
unk062 INT,
unk063 TEXT,
collectible INT,
nodestroy INT,
nonpc INT,
nozone INT,
unk068 INT,
unk069 INT,
unk070 INT,
unk071 INT,
noground INT,
unk073 INT,
marketplace INT,
freestorage INT,
unk076 INT,
unk077 INT,
unk078 INT,
unk079 INT,
evolving INT,
evoid INT,
evolvinglevel INT,
evomax INT,
convertable INT,
convertid INT,
convertname TEXT,
updated INT,
created INT,
submitter TEXT,
verified INT,
verifiedby TEXT,
collectversion TEXT,
idfileextra INT,
mounteffect INT,
mountlevel2 INT,
mounteffecttype INT,
mountlevel INT,
mountunk1 INT,
mountunk2 INT,
mountunk3 INT,
mountunk4 INT,
mountunk5 INT,
mountname TEXT,
mountunk7 INT,
blessinglevel2 INT,
blessingeffecttype INT,
blessinglevel INT,
blessingunk1 INT,
blessingunk2 INT,
blessingunk3 INT,
blessingunk4 INT,
blessingunk5 INT,
blessingunk7 INT,
familiareffect INT,
familiarlevel2 INT,
familiareffecttype INT,
familiarlevel INT,
familiarunk1 INT,
familiarunk2 INT,
familiarunk3 INT,
familiarunk4 INT,
familiarunk5 INT,
familiarname TEXT,
familiarunk7 INT,
unk80 INT,
minluck INT,
maxluck INT,
loreequippedgroup TEXT
);
CREATE INDEX IF NOT EXISTS `idx_raw_item_name` ON `raw_item_data_315` (`name` ASC);
CREATE TABLE IF NOT EXISTS item_links( item_id INTEGER PRIMARY KEY, link TEXT );
CREATE TABLE IF NOT EXISTS db_metadata( key TEXT PRIMARY KEY, value TEXT, description TEXT );)SQL");
}
/* This will update the tables if needed.*/
bool MQ2LinkDBTables::execUpgradeDB(sqlite3 * db)
{
if (db)
{
int currentVersion = getDBVersion(db);
switch (currentVersion)
{
case -1:
WriteChatf("\arMQ2LinkDB: Error determining db schema version.");
break;
case 0:
// upgrade to version 1
{
// add the new column
char* err_msg = nullptr;
std::string query("ALTER TABLE item_links ADD COLUMN item_name TEXT");
if (sqlite3_exec(db, query.c_str(), nullptr, nullptr, &err_msg) != SQLITE_OK)
{
WriteChatf("\ayMQ2LinkDB: Warning preparing query for item_links ALTER TABLE ADD COLUMN: %s", err_msg);
sqlite3_free(err_msg);
// this is okay. don't bail on failure.
}
query = "ALTER TABLE raw_item_data_315 RENAME TO raw_item_data";
if (sqlite3_exec(db, query.c_str(), nullptr, nullptr, &err_msg) != SQLITE_OK)
{
WriteChatf("\ayMQ2LinkDB: Warning preparing query for item_links ALTER TABLE RENAME: %s", err_msg);
sqlite3_free(err_msg);
// this is okay. don't bail on failure.
}
// add an index on item name
query = "CREATE INDEX IF NOT EXISTS `idx_item_links_name` ON `item_links` (`item_name` ASC)";
if (sqlite3_exec(db, query.c_str(), nullptr, nullptr, &err_msg) != SQLITE_OK)
{
WriteChatf("\arMQ2LinkDB: Error preparing query for item_links INDEX: %s", err_msg);
sqlite3_free(err_msg);
return false;
}
if (sqlite3_create_function(db, "extract_link_data", 2, SQLITE_UTF8, NULL, &extract_link_data, NULL, NULL) != SQLITE_OK)
{
WriteChatf("\arMQ2LinkDB: Error creating function for item updates: %s", sqlite3_errmsg(db));
return false;
}
// populate item name into the DB.
query = "UPDATE item_links SET item_name = extract_link_data(link, 1), link = extract_link_data(link, 2)";
if (sqlite3_exec(db, query.c_str(), nullptr, nullptr, &err_msg) != SQLITE_OK)
{
WriteChatf("\arMQ2LinkDB: Error updating item_names: %s", err_msg);
sqlite3_free(err_msg);
return false;
}
// change version to the current version. -- futures functions should UPDATE version instead of insert.
query = R"(INSERT INTO db_metadata(key,value,description) VALUES ('version', '1', 'DB Schema Versioning added, added item_name to item_links table, renamed raw_item_data_315 to raw_item_data.')
ON CONFLICT(key) DO UPDATE SET value='1';)";
if (sqlite3_exec(db, query.c_str(), nullptr, nullptr, &err_msg) != SQLITE_OK)
{
WriteChatf("\arMQ2LinkDB: Error preparing query for db_metadata INSERT: %s", err_msg);
sqlite3_free(err_msg);
return false;
}
}
WriteChatf("\agMQ2LinkDB: Successfully updated DB Schema version to 1!");
// fall through to upgrade to the next version...
[[fallthrough]];
default:
return true;
}
}
return false;
}
int MQ2LinkDBTables::getDBVersion(sqlite3 * db)
{
if (db)
{
sqlite3_stmt* stmt;
constexpr auto query = "SELECT value FROM db_metadata WHERE key = 'version';";
if (sqlite3_prepare_v2(db, query, -1, &stmt, nullptr) != SQLITE_OK)
{
WriteChatf("\arMQ2LinkDB: Error preparing query for item_link: %s", sqlite3_errmsg(db));
return -1;
}
else
{
std::string versionStr("0");
if (sqlite3_step(stmt) == SQLITE_ROW)
{
versionStr = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
}
sqlite3_finalize(stmt);
return std::stoi(versionStr);
}
}
return -1;
}