AMXX-BG.INFO sqlvault.inc Raw include

sqlvault.inc

Original include source with line numbers.

Back Download .inc
1 #if defined _sqlv_included
2 #endinput
3 #endif
4 #define _sqlv_included
5
6 #include <amxmodx>
7 #include <sqlx>
8
9 #if AMXX_VERSION_NUM >= 175
10 #pragma reqlib sqlite
11 #if !defined AMXMODX_NOAUTOLOAD
12 #pragma loadlib sqlite
13 #endif
14 #else
15 #pragma library sqlite
16 #endif
17
18 // debug idea found from xs.inc
19 //#define SQLVAULT_DEBUG_LIB
20
21 #if defined SQLVAULT_DEBUG_LIB
22 #define SQLVAULT_FUNC_ATTRIB
23 #define SQLVAULT_VAR_ATTRIB new
24 #else
25 #define SQLVAULT_FUNC_ATTRIB stock
26 #define SQLVAULT_VAR_ATTRIB stock
27 #endif
28
29 SQLVAULT_VAR_ATTRIB const SQLVAULT_VERSION[] = "0.0.3";
30
31 SQLVAULT_VAR_ATTRIB __SQLVAULT_ERRCODE;
32 SQLVAULT_VAR_ATTRIB __SQLVAULT_ERROR[128];
33 SQLVAULT_VAR_ATTRIB __SQLVAULT_TEMPSTRING[1024];
34
35 enum SQLVault
36 {
37 Invalid_SQLVault = 0
38 };
39
40 /*
41 * Structure used for sqlv_read_all()
42 *
43 * @elem SQLV_Key - String that holds the key
44 * @elem SQLV_Data - String that holds the data
45 * @elem SQLV_TimeStamp - Integer that holds the timestamp
46 *
47 */
48 enum _:SQLVaultEntry
49 {
50 SQLV_Key[64],
51 SQLV_Data[512],
52 SQLV_TimeStamp
53 };
54
55 /*
56 * Opens a vault database
57 *
58 * @param szHost - The host used to connect to the database
59 * @param szUser - The user used to connect to the database
60 * @param szPass - The password used to connect to the database
61 * @param szDb - The name of the database to connect to
62 * @param szVaultName - The vault name to open
63 * @param bAutoInit - If true, sqlv_init() is called inside the function. If false, sqlv_init() is not called.
64 *
65 * @return Returns a valid vault handle on success, Invalid_SQLVault on failure.
66 *
67 */
68 SQLVAULT_FUNC_ATTRIB SQLVault:sqlv_open(szHost[], szUser[], szPass[], szDb[], szVaultName[], bool:bAutoInit = true)
69 {
70 new Handle:hTuple = SQL_MakeDbTuple(szHost, szUser, szPass, szDb);
71
72 if(hTuple == Empty_Handle)
73 {
74 log_amx("Could not create SQL tuple");
75
76 return Invalid_SQLVault;
77 }
78
79 QuoteString(szVaultName, '`');
80
81 new Trie:tVaultData = TrieCreate();
82
83 TrieSetCell(tVaultData, "tuple", hTuple);
84 TrieSetString(tVaultData, "vaultname", szVaultName);
85
86 UnQuoteString(szVaultName, '`');
87
88 if(bAutoInit && !sqlv_init(SQLVault:tVaultData))
89 {
90 SQL_FreeHandle(hTuple);
91
92 TrieDestroy(tVaultData);
93
94 return Invalid_SQLVault;
95 }
96
97 return SQLVault:tVaultData;
98 }
99
100 /*
101 * Opens a vault database based on the amx_sql_* cvars in addons/amxmodx/configs/sql.cfg
102 *
103 * @param szVaultName - The vault name to open
104 * @param bAutoInit - If true, sqlv_init() is called inside the function. If false, sqlv_init() is not called.
105 *
106 * @return Returns a valid vault handle on success, Invalid_SQLVault on failure.
107 *
108 */
109 SQLVAULT_FUNC_ATTRIB SQLVault:sqlv_open_default(szVaultName[], bool:bAutoInit = true)
110 {
111 // code taken from SQL_MakeStdTuple()
112
113 new szConfigsDir[64];
114 get_localinfo("amxx_configsdir", szConfigsDir, charsmax(szConfigsDir));
115
116 server_cmd("exec %s/sql.cfg", szConfigsDir);
117 server_exec();
118
119 new szHost[64], szUser[64], szPass[64], szDb[64], szSetType[12];
120 get_cvar_string("amx_sql_host", szHost, charsmax(szHost));
121 get_cvar_string("amx_sql_user", szUser, charsmax(szUser));
122 get_cvar_string("amx_sql_pass", szPass, charsmax(szPass));
123 get_cvar_string("amx_sql_db", szDb, charsmax(szDb));
124 get_cvar_string("amx_sql_type", szSetType, charsmax(szSetType));
125
126 if(!sqlv_affinity(szSetType))
127 {
128 return Invalid_SQLVault;
129 }
130
131 return sqlv_open(szHost, szUser, szPass, szDb, szVaultName, bAutoInit);
132 }
133
134 /*
135 * Opens a local vault database using the sqlite module
136 *
137 * @param szVaultName - The vault name to open
138 * @param bAutoInit - If true, sqlv_init() is called inside the function. If false, sqlv_init() is not called.
139 *
140 * @return Returns a valid vault handle on success, Invalid_SQLVault on failure.
141 *
142 */
143 SQLVAULT_FUNC_ATTRIB SQLVault:sqlv_open_local(szVaultName[], bool:bAutoInit = true)
144 {
145 static SQLITE_HOST[] = "127.0.0.1";
146 static SQLITE_USER[] = "root";
147 static SQLITE_PASS[] = "";
148 static SQLITE_DB[] = "amx";
149
150 // added requirement for "sqlite" library at top of .inc
151 /*if(!is_module_loaded("sqlite"))
152 {
153 log_amx("SQLite module needs to be enabled in modules.ini to open local database!");
154
155 return Invalid_SQLVault;
156 }*/
157
158 if(!sqlv_affinity("sqlite"))
159 {
160 return Invalid_SQLVault;
161 }
162
163 return sqlv_open(SQLITE_HOST, SQLITE_USER, SQLITE_PASS, SQLITE_DB, szVaultName, bAutoInit);
164 }
165
166 /*
167 * Sets the SQL driver
168 *
169 * @param szSetType - The driver to set
170 *
171 * @return Returns 1 on success, 0 on failure.
172 *
173 */
174 SQLVAULT_FUNC_ATTRIB sqlv_affinity(szSetType[])
175 {
176 new szGetType[12];
177 SQL_GetAffinity(szGetType, charsmax(szGetType));
178
179 if(!equali(szGetType, szSetType) && !SQL_SetAffinity(szSetType))
180 {
181 log_amx("Failed to set affinity from %s to %s.", szGetType, szSetType);
182
183 return 0;
184 }
185
186 return 1;
187 }
188
189 /*
190 * Closes the vault
191 *
192 * @param hVault - The vault to close
193 *
194 * @return No return
195 *
196 * @note The vault handle is set to Invalid_SQLVault after it is closed.
197 *
198 */
199 SQLVAULT_FUNC_ATTRIB sqlv_close(&SQLVault:hVault)
200 {
201 if(hVault == Invalid_SQLVault)
202 {
203 return;
204 }
205
206 new Handle:hTuple;
207 TrieGetCell(Trie:hVault, "tuple", hTuple);
208
209 SQL_FreeHandle(hTuple);
210
211 if(TrieGetCell(Trie:hVault, "connection", hTuple))
212 {
213 SQL_FreeHandle(hTuple);
214 }
215
216 TrieDestroy(Trie:hVault);
217
218 hVault = Invalid_SQLVault;
219 }
220
221 /*
222 * Connects to the vault database
223 *
224 * @param hVault - The vault to connect to
225 *
226 * @return Returns 1 on success, 0 on failure.
227 *
228 * @note This does not open the vault!
229 * It only creates a cached connection.
230 *
231 * @note This should be used when multiple vault functions are used in a row
232 * Doing this will reduce CPU usage in connecting/disconnecting each time those functions are used.
233 *
234 * @note After those functions are used, this connection should be closed.
235 *
236 * @note It is not recommended to keep the connection open the whole time the plugin is running.
237 *
238 */
239 SQLVAULT_FUNC_ATTRIB sqlv_connect(SQLVault:hVault)
240 {
241 if(hVault == Invalid_SQLVault)
242 {
243 return 0;
244 }
245
246 new Handle:hTuple;
247 TrieGetCell(Trie:hVault, "tuple", hTuple);
248
249 if(hTuple == Empty_Handle)
250 {
251 return 0;
252 }
253
254 if(TrieKeyExists(Trie:hVault, "connection"))
255 {
256 return 1;
257 }
258
259 new Handle:hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
260
261 if(hConnection == Empty_Handle)
262 {
263 log_amx("Connection failed in sqlv_connect() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
264
265 return 0;
266 }
267
268 TrieSetCell(Trie:hVault, "connection", hConnection);
269
270 return 1;
271 }
272
273 /*
274 * Disconnects from the vault database
275 *
276 * @param hVault - The vault to disconnect
277 *
278 * @return Returns 1 if disconnected, 0 on error or no connection existed.
279 *
280 * @note This does not close the vault!
281 * It only closes the cached connection made.
282 *
283 */
284 SQLVAULT_FUNC_ATTRIB sqlv_disconnect(SQLVault:hVault)
285 {
286 if(hVault == Invalid_SQLVault)
287 {
288 return 0;
289 }
290
291 new Handle:hTuple;
292 TrieGetCell(Trie:hVault, "tuple", hTuple);
293
294 if(hTuple == Empty_Handle)
295 {
296 return 0;
297 }
298
299 new Handle:hConnection;
300
301 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
302 {
303 return 0;
304 }
305
306 SQL_FreeHandle(hConnection);
307
308 TrieDeleteKey(Trie:hVault, "connection");
309
310 return 1;
311 }
312
313 /*
314 * Initializes the vault for use
315 *
316 * @param hVault - The vault to initialize
317 *
318 * @return Returns 1 on success, 0 on failure
319 *
320 * @note This must be used before any other vault functions are used (except open and close)!
321 *
322 */
323 SQLVAULT_FUNC_ATTRIB sqlv_init(SQLVault:hVault)
324 {
325 if(hVault == Invalid_SQLVault)
326 {
327 return 0;
328 }
329
330 new Handle:hTuple;
331 TrieGetCell(Trie:hVault, "tuple", hTuple);
332
333 if(hTuple == Empty_Handle)
334 {
335 return 0;
336 }
337
338 new Handle:hConnection, bool:bNewConnection = false;
339
340 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
341 {
342 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
343
344 if(hConnection == Empty_Handle)
345 {
346 log_amx("Connection failed in sqlv_init() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
347
348 return 0;
349 }
350
351 bNewConnection = true;
352 }
353
354 new szVaultName[32];
355 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
356
357 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
358 "CREATE TABLE IF NOT EXISTS `%s` \
359 (`key` VARCHAR(64) NOT NULL PRIMARY KEY, \
360 `data` VARCHAR(512) NOT NULL, \
361 `timestamp` INT(11) NOT NULL, \
362 `permanent` INT(11) NOT NULL);",
363 szVaultName);
364
365 new iReturn = 1;
366
367 if(!SQL_Execute(hQuery))
368 {
369 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
370 log_amx("Error in sqlv_init(): %s", __SQLVAULT_ERROR);
371
372 iReturn = 0;
373 }
374
375 SQL_FreeHandle(hQuery);
376
377 if(bNewConnection)
378 {
379 SQL_FreeHandle(hConnection);
380 }
381
382 return iReturn;
383 }
384
385 /*
386 * Gets a string value from a vault
387 *
388 * @param hVault - The vault to get the data from
389 * @param szKey - The key holding the data
390 * @param szData - The buffer to hold the data
391 * @param iDataLen - The max length of the data buffer
392 * @param iTimeStamp - The byref variable holding the timestamp
393 *
394 * @return Returns 1 on success, 0 on failure
395 *
396 */
397 SQLVAULT_FUNC_ATTRIB sqlv_get_data(SQLVault:hVault, szKey[], szData[], iDataLen, &iTimeStamp = 0)
398 {
399 szData[0] = 0;
400
401 iTimeStamp = 0;
402
403 if(hVault == Invalid_SQLVault)
404 {
405 return 0;
406 }
407
408 new Handle:hTuple;
409 TrieGetCell(Trie:hVault, "tuple", hTuple);
410
411 if(hTuple == Empty_Handle)
412 {
413 return 0;
414 }
415
416 new Handle:hConnection, bool:bNewConnection = false;
417
418 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
419 {
420 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
421
422 if(hConnection == Empty_Handle)
423 {
424 log_amx("Connection failed in sqlv_get_data() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
425
426 return 0;
427 }
428
429 bNewConnection = true;
430 }
431
432 new szVaultName[32];
433 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
434
435 QuoteString(szKey);
436
437 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
438 "SELECT `data`, `timestamp` \
439 FROM `%s` \
440 WHERE `key` = '%s';",
441 szVaultName, szKey);
442
443 UnQuoteString(szKey);
444
445 new iReturn = 0;
446
447 if(!SQL_Execute(hQuery))
448 {
449 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
450 log_amx("Error in sqlv_get_data(): %s", __SQLVAULT_ERROR);
451 }
452 else if((iReturn = SQL_NumResults(hQuery)))
453 {
454 SQL_ReadResult(hQuery, 0, szData, iDataLen);
455
456 iTimeStamp = SQL_ReadResult(hQuery, 1);
457 }
458
459 SQL_FreeHandle(hQuery);
460
461 if(bNewConnection)
462 {
463 SQL_FreeHandle(hConnection);
464 }
465
466 return iReturn;
467 }
468
469 /*
470 * Gets an integer value from a vault
471 *
472 * @param hVault - The vault to get the data from
473 * @param szKey - The key holding the data
474 * @param iTimeStamp - The byref variable holding the timestamp
475 *
476 * @return Returns the integer value on success, 0 on failure
477 *
478 */
479 SQLVAULT_FUNC_ATTRIB sqlv_get_num(SQLVault:hVault, szKey[], &iTimeStamp = 0)
480 {
481 if(sqlv_get_data(hVault, szKey, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING), iTimeStamp))
482 {
483 return str_to_num(__SQLVAULT_TEMPSTRING);
484 }
485
486 return 0;
487 }
488
489 /*
490 * Gets a float value from a vault
491 *
492 * @param hVault - The vault to get the data from
493 * @param szKey - The key holding the data
494 * @param iTimeStamp - The byref variable holding the timestamp
495 *
496 * @return Returns the float value on success, 0.0 on failure
497 *
498 */
499 SQLVAULT_FUNC_ATTRIB Float:sqlv_get_float(SQLVault:hVault, szKey[], &iTimeStamp = 0)
500 {
501 if(sqlv_get_data(hVault, szKey, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING), iTimeStamp))
502 {
503 return str_to_float(__SQLVAULT_TEMPSTRING);
504 }
505
506 return 0.0;
507 }
508
509 /*
510 * Checks if a key exists in a vault
511 *
512 * @param hVault - The vault to look in
513 * @param szKey - The key to look for
514 *
515 * @return Returns 1 if exists, 0 if it doesn't.
516 *
517 */
518 SQLVAULT_FUNC_ATTRIB sqlv_key_exists(SQLVault:hVault, szKey[])
519 {
520 return sqlv_get_data(hVault, szKey, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
521 }
522
523 /*
524 * Sets a vault entry to a string value
525 *
526 * @param hVault - The vault to set the data in
527 * @param szKey - The key to hold the data
528 * @param szData - The string value to set
529 *
530 * @return Returns 1 on success, 0 on failure.
531 *
532 * @note Use "*" for the key to set all entries to that data.
533 * This will update all the timestamps and also set all to non-permanent (even permanent entries)!
534 *
535 */
536 SQLVAULT_FUNC_ATTRIB sqlv_set_data(SQLVault:hVault, szKey[], szData[])
537 {
538 if(hVault == Invalid_SQLVault)
539 {
540 return 0;
541 }
542
543 new Handle:hTuple;
544 TrieGetCell(Trie:hVault, "tuple", hTuple);
545
546 if(hTuple == Empty_Handle)
547 {
548 return 0;
549 }
550
551 new Handle:hConnection, bool:bNewConnection = false;
552
553 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
554 {
555 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
556
557 if(hConnection == Empty_Handle)
558 {
559 log_amx("Connection failed in sqlv_set_data() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
560
561 return 0;
562 }
563
564 bNewConnection = true;
565 }
566
567 new szVaultName[32];
568 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
569
570 QuoteString(szData);
571
572 new Handle:hQuery;
573
574 if(equal(szKey, "*"))
575 {
576 hQuery = SQL_PrepareQuery(hConnection,\
577 "UPDATE `%s` \
578 SET `data` = '%s' \
579 AND `timestamp` = %d \
580 AND `permanent` = 0;",\
581 szVaultName, szData, get_systime());
582 }
583 else
584 {
585 QuoteString(szKey);
586
587 hQuery = SQL_PrepareQuery(hConnection,\
588 "REPLACE INTO `%s` \
589 (`key`, `data`, `timestamp`, `permanent`) \
590 VALUES \
591 ('%s', '%s', %d, 0);",\
592 szVaultName, szKey, szData, get_systime());
593
594 UnQuoteString(szKey);
595 }
596
597 UnQuoteString(szData);
598
599 new iReturn = 0;
600
601 if(!SQL_Execute(hQuery))
602 {
603 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
604 log_amx("Error in sqlv_set_data(): %s", __SQLVAULT_ERROR);
605 }
606 else
607 {
608 iReturn = 1;
609 }
610
611 SQL_FreeHandle(hQuery);
612
613 if(bNewConnection)
614 {
615 SQL_FreeHandle(hConnection);
616 }
617
618 return iReturn;
619 }
620
621 /*
622 * Sets a vault entry to an integer value
623 *
624 * @param hVault - The vault to set the data in
625 * @param szKey - The key to hold the data
626 * @param iData - The integer value to set
627 *
628 * @return Returns 1 on success, 0 on failure.
629 *
630 * @note Use "*" for the key to set all entries to that data.
631 * This will update all the timestamps and also set all to non-permanent (even permanent entries)!
632 *
633 */
634 SQLVAULT_FUNC_ATTRIB sqlv_set_num(SQLVault:hVault, szKey[], const iData)
635 {
636 num_to_str(iData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
637
638 return sqlv_set_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
639 }
640
641 /*
642 * Sets a vault entry to a float value
643 *
644 * @param hVault - The vault to set the data in
645 * @param szKey - The key to hold the data
646 * @param flData - The float value to set
647 *
648 * @return Returns 1 on success, 0 on failure.
649 *
650 * @note Use "*" for the key to set all entries to that data.
651 * This will update all the timestamps and also set all to non-permanent (even permanent entries)!
652 *
653 */
654 SQLVAULT_FUNC_ATTRIB sqlv_set_float(SQLVault:hVault, szKey[], Float:flData)
655 {
656 float_to_str(flData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
657
658 return sqlv_set_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
659 }
660
661 /*
662 * Sets a vault entry to a string value with a permanent entry
663 *
664 * @param hVault - The vault to set the data in
665 * @param szKey - The key to hold the data
666 * @param szData - The string value to set
667 *
668 * @return Returns 1 on success, 0 on failure.
669 *
670 * @note Permanent means that the entry cannot be deleted by sqlv_prune().
671 *
672 * @note Use "*" for the key to set all entries to that data.
673 * This will update all the timestamps and also set all to permanent (even non-permanent entries)!
674 *
675 */
676 SQLVAULT_FUNC_ATTRIB sqlv_pset_data(SQLVault:hVault, szKey[], szData[])
677 {
678 if(hVault == Invalid_SQLVault)
679 {
680 return 0;
681 }
682
683 new Handle:hTuple;
684 TrieGetCell(Trie:hVault, "tuple", hTuple);
685
686 if(hTuple == Empty_Handle)
687 {
688 return 0;
689 }
690
691 new Handle:hConnection, bool:bNewConnection = false;
692
693 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
694 {
695 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
696
697 if(hConnection == Empty_Handle)
698 {
699 log_amx("Connection failed in sqlv_pset_data() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
700
701 return 0;
702 }
703
704 bNewConnection = true;
705 }
706
707 new szVaultName[32];
708 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
709
710 QuoteString(szData);
711
712 new Handle:hQuery;
713
714 if(equal(szKey, "*"))
715 {
716 hQuery = SQL_PrepareQuery(hConnection,\
717 "UPDATE `%s` \
718 SET `data` = '%s' \
719 AND `timestamp` = %d \
720 AND `permanent` = 1;",\
721 szVaultName, szData, get_systime());
722 }
723 else
724 {
725 QuoteString(szKey);
726
727 hQuery = SQL_PrepareQuery(hConnection,\
728 "REPLACE INTO `%s` \
729 (`key`, `data`, `timestamp`, `permanent`) \
730 VALUES \
731 ('%s', '%s', %d, 1);",\
732 szVaultName, szKey, szData, get_systime());
733
734 UnQuoteString(szKey);
735 }
736
737 UnQuoteString(szData);
738
739 new iReturn = 0;
740
741 if(!SQL_Execute(hQuery))
742 {
743 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
744 log_amx("Error in sqlv_set_data(): %s", __SQLVAULT_ERROR);
745 }
746 else
747 {
748 iReturn = 1;
749 }
750
751 SQL_FreeHandle(hQuery);
752
753 if(bNewConnection)
754 {
755 SQL_FreeHandle(hConnection);
756 }
757
758 return iReturn;
759 }
760
761 /*
762 * Sets a vault entry to an integer value with a permanent entry
763 *
764 * @param hVault - The vault to set the data in
765 * @param szKey - The key to hold the data
766 * @param iData - The integer value to set
767 *
768 * @return Returns 1 on success, 0 on failure.
769 *
770 * @note Permanent means that the entry cannot be deleted by sqlv_prune().
771 *
772 * @note Use "*" for the key to set all entries to that data.
773 * This will update all the timestamps and also set all to permanent (even non-permanent entries)!
774 *
775 */
776 SQLVAULT_FUNC_ATTRIB sqlv_pset_num(SQLVault:hVault, szKey[], const iData)
777 {
778 num_to_str(iData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
779
780 return sqlv_pset_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
781 }
782
783 /*
784 * Sets a vault entry to a float value with a permanent entry
785 *
786 * @param hVault - The vault to set the data in
787 * @param szKey - The key to hold the data
788 * @param flData - The float value to set
789 *
790 * @return Returns 1 on success, 0 on failure.
791 *
792 * @note Permanent means that the entry cannot be deleted by sqlv_prune().
793 *
794 * @note Use "*" for the key to set all entries to that data.
795 * This will update all the timestamps and also set all to permanent (even non-permanent entries)!
796 *
797 */
798 SQLVAULT_FUNC_ATTRIB sqlv_pset_float(SQLVault:hVault, szKey[], Float:flData)
799 {
800 float_to_str(flData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
801
802 return sqlv_pset_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
803 }
804
805 /*
806 * Removes a key from a vault
807 *
808 * @param hVault - The vault to delete the key from
809 * @param szKey - The key to delete
810 *
811 * @return Returns 1 on success, 0 on failure.
812 *
813 */
814 SQLVAULT_FUNC_ATTRIB sqlv_remove(SQLVault:hVault, szKey[])
815 {
816 if(hVault == Invalid_SQLVault)
817 {
818 return 0;
819 }
820
821 new Handle:hTuple;
822 TrieGetCell(Trie:hVault, "tuple", hTuple);
823
824 if(hTuple == Empty_Handle)
825 {
826 return 0;
827 }
828
829 new Handle:hConnection, bool:bNewConnection = false;
830
831 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
832 {
833 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
834
835 if(hConnection == Empty_Handle)
836 {
837 log_amx("Connection failed in sqlv_remove() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
838
839 return 0;
840 }
841
842 bNewConnection = true;
843 }
844
845 new szVaultName[32];
846 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
847
848 QuoteString(szKey);
849
850 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
851 "DELETE FROM `%s` \
852 WHERE `key` = '%s';",
853 szVaultName, szKey);
854
855 UnQuoteString(szKey);
856
857 new iReturn = 0;
858
859 if(!SQL_Execute(hQuery))
860 {
861 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
862 log_amx("Error in sqlv_remove(): %s", __SQLVAULT_ERROR);
863 }
864 else if(!(iReturn = SQL_AffectedRows(hQuery)))
865 {
866 iReturn = 1;
867 }
868
869 SQL_FreeHandle(hQuery);
870
871 if(bNewConnection)
872 {
873 SQL_FreeHandle(hConnection);
874 }
875
876 return iReturn;
877 }
878
879 /*
880 * Removes all non-permanent entries in a vault that have a timestamp between the start and end timestamps
881 *
882 * @param hVault - The vault to prune
883 * @param iStart - The start timestamp
884 * @param iEnd - The end timestamp
885 *
886 * @return Returns the number of deleted entries (or 1 if none deleted) on success, 0 on failure.
887 *
888 */
889 SQLVAULT_FUNC_ATTRIB sqlv_prune(SQLVault:hVault, iStart, iEnd)
890 {
891 if(hVault == Invalid_SQLVault)
892 {
893 return 0;
894 }
895
896 new Handle:hTuple;
897 TrieGetCell(Trie:hVault, "tuple", hTuple);
898
899 if(hTuple == Empty_Handle)
900 {
901 return 0;
902 }
903
904 new Handle:hConnection, bool:bNewConnection = false;
905
906 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
907 {
908 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
909
910 if(hConnection == Empty_Handle)
911 {
912 log_amx("Connection failed in sqlv_prune() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
913
914 return 0;
915 }
916
917 bNewConnection = true;
918 }
919
920 new szVaultName[32];
921 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
922
923 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
924 "DELETE FROM `%s` \
925 WHERE `permanent` = 0 \
926 AND %d <= `timestamp` \
927 AND `timestamp` <= %d;",
928 szVaultName, iStart, iEnd);
929
930 new iReturn = 0;
931
932 if(!SQL_Execute(hQuery))
933 {
934 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
935 log_amx("Error in sqlv_prune(): %s", __SQLVAULT_ERROR);
936 }
937 else if(!(iReturn = SQL_AffectedRows(hQuery)))
938 {
939 iReturn = 1;
940 }
941
942 SQL_FreeHandle(hQuery);
943
944 if(bNewConnection)
945 {
946 SQL_FreeHandle(hConnection);
947 }
948
949 return iReturn;
950 }
951
952 /*
953 * Updates the timestamp for a key in a vault
954 *
955 * @param hVault - The vault to update the key in
956 * @param szKey - The key to update the timestamp for
957 * @param iTimeStamp - The timestamp to set for the vault (optional, default is -1)
958 *
959 * @return Returns 1 on success, 0 on failure.
960 *
961 * @note Use -1 for timestamp to update with the current timestamp
962 *
963 * @note Use "*" for the key to touch all entries.
964 *
965 */
966 SQLVAULT_FUNC_ATTRIB sqlv_touch(SQLVault:hVault, szKey[], iTimeStamp = -1)
967 {
968 if(hVault == Invalid_SQLVault)
969 {
970 return 0;
971 }
972
973 new Handle:hTuple;
974 TrieGetCell(Trie:hVault, "tuple", hTuple);
975
976 if(hTuple == Empty_Handle)
977 {
978 return 0;
979 }
980
981 new Handle:hConnection, bool:bNewConnection = false;
982
983 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
984 {
985 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
986
987 if(hConnection == Empty_Handle)
988 {
989 log_amx("Connection failed in sqlv_touch() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
990
991 return 0;
992 }
993
994 bNewConnection = true;
995 }
996
997 new szVaultName[32];
998 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
999
1000 if(iTimeStamp < 0)
1001 {
1002 iTimeStamp = get_systime();
1003 }
1004
1005 new Handle:hQuery;
1006
1007 if(equal(szKey, "*"))
1008 {
1009 hQuery = SQL_PrepareQuery(hConnection,\
1010 "UPDATE `%s` \
1011 SET `timestamp` = %d;",
1012 szVaultName, iTimeStamp);
1013 }
1014 else
1015 {
1016 QuoteString(szKey);
1017
1018 hQuery = SQL_PrepareQuery(hConnection,\
1019 "UPDATE `%s` \
1020 SET `timestamp` = %d \
1021 WHERE `key` = '%s';",
1022 szVaultName, iTimeStamp, szKey);
1023
1024 UnQuoteString(szKey);
1025 }
1026
1027 new iReturn = 0;
1028
1029 if(!SQL_Execute(hQuery))
1030 {
1031 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
1032 log_amx("Error in sqlv_touch(): %s", __SQLVAULT_ERROR);
1033 }
1034 else if(!(iReturn = SQL_AffectedRows(hQuery)))
1035 {
1036 iReturn = 1;
1037 }
1038
1039 SQL_FreeHandle(hQuery);
1040
1041 if(bNewConnection)
1042 {
1043 SQL_FreeHandle(hConnection);
1044 }
1045
1046 return iReturn;
1047 }
1048
1049 /*
1050 * Deletes all entries in a vault
1051 *
1052 * @param hVault - The vault to delete entries from
1053 * @param bSavePermanent - If true, deletes only entries that are not permanent. If false, deletes all entries. (optional, default is false)
1054 *
1055 * @return Returns total entries deleted (or 1 if empty) on success, 0 on failure.
1056 *
1057 */
1058 SQLVAULT_FUNC_ATTRIB sqlv_clear(SQLVault:hVault, bool:bSavePermanent = false)
1059 {
1060 if(hVault == Invalid_SQLVault)
1061 {
1062 return 0;
1063 }
1064
1065 new Handle:hTuple;
1066 TrieGetCell(Trie:hVault, "tuple", hTuple);
1067
1068 if(hTuple == Empty_Handle)
1069 {
1070 return 0;
1071 }
1072
1073 new Handle:hConnection, bool:bNewConnection = false;
1074
1075 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
1076 {
1077 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
1078
1079 if(hConnection == Empty_Handle)
1080 {
1081 log_amx("Connection failed in sqlv_clear() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
1082
1083 return 0;
1084 }
1085
1086 bNewConnection = true;
1087 }
1088
1089 new szVaultName[32];
1090 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
1091
1092 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
1093 "DELETE FROM `%s`%s;",
1094 szVaultName, bSavePermanent ? " WHERE `permanent` = 0" : "");
1095
1096 new iReturn = 0;
1097
1098 if(!SQL_Execute(hQuery))
1099 {
1100 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
1101 log_amx("Error in sqlv_clear(): %s", __SQLVAULT_ERROR);
1102 }
1103 else if(!(iReturn = SQL_AffectedRows(hQuery)))
1104 {
1105 iReturn = 1;
1106 }
1107
1108 SQL_FreeHandle(hQuery);
1109
1110 if(bNewConnection)
1111 {
1112 SQL_FreeHandle(hConnection);
1113 }
1114
1115 return iReturn;
1116 }
1117
1118 /*
1119 * Gets the total number of entries in the vault
1120 *
1121 * @param hVault - The vault to find the size of
1122 *
1123 * @return Returns the total number of entries in the vault
1124 *
1125 */
1126 SQLVAULT_FUNC_ATTRIB sqlv_size(SQLVault:hVault)
1127 {
1128 if(hVault == Invalid_SQLVault)
1129 {
1130 return 0;
1131 }
1132
1133 new Handle:hTuple;
1134 TrieGetCell(Trie:hVault, "tuple", hTuple);
1135
1136 if(hTuple == Empty_Handle)
1137 {
1138 return 0;
1139 }
1140
1141 new Handle:hConnection, bool:bNewConnection = false;
1142
1143 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
1144 {
1145 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
1146
1147 if(hConnection == Empty_Handle)
1148 {
1149 log_amx("Connection failed in sqlv_size() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
1150
1151 return 0;
1152 }
1153
1154 bNewConnection = true;
1155 }
1156
1157 new szVaultName[32];
1158 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
1159
1160 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
1161 "SELECT COUNT(*) FROM `%s`;",
1162 szVaultName);
1163
1164 new iReturn = 0;
1165
1166 if(!SQL_Execute(hQuery))
1167 {
1168 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
1169 log_amx("Error in sqlv_size(): %s", __SQLVAULT_ERROR);
1170 }
1171 else if(SQL_NumResults(hQuery))
1172 {
1173 iReturn = SQL_ReadResult(hQuery, 0);
1174 }
1175
1176 SQL_FreeHandle(hQuery);
1177
1178 if(bNewConnection)
1179 {
1180 SQL_FreeHandle(hConnection);
1181 }
1182
1183 return iReturn;
1184 }
1185
1186 /*
1187 * Reads a vault by key index
1188 *
1189 * @param hVault - The vault to read from
1190 * @param iKeyIndex - The key index to read
1191 * @param szKey - The string to hold the key (optional)
1192 * @param iKeyLen - The max length of the key buffer (optional)
1193 * @param szData - The string to hold the data (optional)
1194 * @param iDataLen - The max length of the data buffer (optional)
1195 * @param iTimeStamp - The byref variable that holds the timestamp (optional)
1196 * @param szWhere - The where condition for selecting specific vault data (optional)
1197 * @param szSort - The method to sort the vault data by (optional)
1198 *
1199 * @return Returns 1 on success, 0 on failure.
1200 *
1201 * @note Key indexes start at 0 and stop at 1 before the size of the vault (sqlv_size() - 1)
1202 *
1203 * @note If you want to read all keys in the vault, use sqlv_read_all().
1204 *
1205 * @note If a vault is changed by setting data, changing timestamps, deleteing, etc. then the key indexes may change.
1206 * Therefore, those type of actions should not be done if more than 1 key is being read.
1207 *
1208 * @note The where condition is the same as the where clause from MySQL's SELECT statement.
1209 * Do not include "WHERE" inside the where clause.
1210 *
1211 * @note Sorting the vault data can be done 2 ways:
1212 * 1. Pass "asc" to sort in ascending order by the data value
1213 * Pass "desc" to sort in descending order by the data value
1214 * 2. Pass any other string to format the ORDER BY clause from MySQL
1215 * Do not include "ORDER BY" inside the sort string
1216 *
1217 */
1218 SQLVAULT_FUNC_ATTRIB sqlv_read(SQLVault:hVault, iKeyIndex, szKey[] = "", iKeyLen = 0, szData[] = "", iDataLen = 0, &iTimeStamp = 0, const szWhere[] = "", const szSort[] = "")
1219 {
1220 if(iKeyLen)
1221 {
1222 szKey[0] = 0;
1223 }
1224
1225 if(iDataLen)
1226 {
1227 szData[0] = 0;
1228 }
1229
1230 iTimeStamp = 0;
1231
1232 new szFixedWhere[256], szFixedSort[256];
1233
1234 if(szWhere[0])
1235 {
1236 formatex(szFixedWhere, charsmax(szFixedWhere), " WHERE %s", szWhere);
1237 }
1238
1239 if(szSort[0])
1240 {
1241 if(equali(szSort, "asc") || equali(szSort, "desc"))
1242 {
1243 formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY `data` %s", szSort);
1244 }
1245 else
1246 {
1247 formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY %s", szSort);
1248 }
1249 }
1250
1251 if(hVault == Invalid_SQLVault)
1252 {
1253 return 0;
1254 }
1255
1256 new Handle:hTuple;
1257 TrieGetCell(Trie:hVault, "tuple", hTuple);
1258
1259 if(hTuple == Empty_Handle)
1260 {
1261 return 0;
1262 }
1263
1264 new Handle:hConnection, bool:bNewConnection = false;
1265
1266 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
1267 {
1268 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
1269
1270 if(hConnection == Empty_Handle)
1271 {
1272 log_amx("Connection failed in sqlv_read() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
1273
1274 return 0;
1275 }
1276
1277 bNewConnection = true;
1278 }
1279
1280 new szVaultName[32];
1281 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
1282
1283 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
1284 "SELECT `key`, `data`, `timestamp` FROM `%s`%s%s LIMIT %d, 1;",
1285 szVaultName, iKeyIndex, szFixedWhere, szFixedSort);
1286
1287 new iReturn = 0;
1288
1289 if(!SQL_Execute(hQuery))
1290 {
1291 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
1292 log_amx("Error in sqlv_read(): %s", __SQLVAULT_ERROR);
1293 }
1294 else if(SQL_NumResults(hQuery))
1295 {
1296 iReturn = 1;
1297
1298 if(iKeyLen)
1299 {
1300 SQL_ReadResult(hQuery, 0, szKey, iKeyLen);
1301 }
1302
1303 if(iDataLen)
1304 {
1305 SQL_ReadResult(hQuery, 1, szData, iDataLen);
1306 }
1307
1308 iTimeStamp = SQL_ReadResult(hQuery, 2);
1309 }
1310
1311 SQL_FreeHandle(hQuery);
1312
1313 if(bNewConnection)
1314 {
1315 SQL_FreeHandle(hConnection);
1316 }
1317
1318 return iReturn;
1319 }
1320
1321 /*
1322 * Reads all of the vault data into a cell array
1323 *
1324 * @param hVault - The vault to read from
1325 * @param aVaultData - The cell array to hold the data
1326 * @param szWhere - The where condition for selecting specific vault data (optional)
1327 * @param szSort - The method to sort the vault data by (optional)
1328 *
1329 * @return Returns the total number of vault entries
1330 *
1331 * @note The where condition is the same as the where clause from MySQL's SELECT statement.
1332 * Do not include "WHERE" inside the where clause.
1333 *
1334 * @note Sorting the vault data can be done 2 ways:
1335 * 1. Pass "asc" to sort in ascending order by the data value
1336 * Pass "desc" to sort in descending order by the data value
1337 * 2. Pass any other string to format the ORDER BY clause from MySQL
1338 * Do not include "ORDER BY" inside the sort string
1339 *
1340 * @note The cell array contains arrays that correspond to the SQLVaultEntry enum
1341 *
1342 * @note Example:
1343 *
1344 * new Array:aVaultData;
1345 * new iVaultKeys = sqlv_read_all(hVault, aVaultData);
1346 *
1347 * new eVaultData[SQLVaultEntry];
1348 *
1349 * for(new i = 0; i < iVaultKeys; i++)
1350 * {
1351 * ArrayGetArray(aVaultData, i, eVaultData);
1352 *
1353 * eVaultData[SQLV_Key] = key
1354 * eVaultData[SQLV_Data] = data
1355 * eVaultData[SQLV_TimeStamp] = timestamp
1356 * }
1357 *
1358 * ArrayDestroy(aVaultData);
1359 *
1360 * @note The cell array should not be created.
1361 * It is auto-created in the function.
1362 * If the cell array already contains a handle, it is destroyed first.
1363 *
1364 * @note The cell array needs to be destroyed after being used
1365 *
1366 */
1367 SQLVAULT_FUNC_ATTRIB sqlv_read_all(SQLVault:hVault, &Array:aVaultData, const szWhere[] = "", const szSort[] = "")
1368 {
1369 if(aVaultData != Invalid_Array)
1370 {
1371 ArrayDestroy(aVaultData);
1372 }
1373
1374 aVaultData = ArrayCreate(SQLVaultEntry);
1375
1376 new szFixedWhere[256], szFixedSort[256];
1377
1378 if(szWhere[0])
1379 {
1380 formatex(szFixedWhere, charsmax(szFixedWhere), " WHERE %s", szWhere);
1381 }
1382
1383 if(szSort[0])
1384 {
1385 if(equali(szSort, "asc") || equali(szSort, "desc"))
1386 {
1387 formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY `data` %s", szSort);
1388 }
1389 else
1390 {
1391 formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY %s", szSort);
1392 }
1393 }
1394
1395 if(hVault == Invalid_SQLVault)
1396 {
1397 return 0;
1398 }
1399
1400 new Handle:hTuple;
1401 TrieGetCell(Trie:hVault, "tuple", hTuple);
1402
1403 if(hTuple == Empty_Handle)
1404 {
1405 return 0;
1406 }
1407
1408 new Handle:hConnection, bool:bNewConnection = false;
1409
1410 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
1411 {
1412 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
1413
1414 if(hConnection == Empty_Handle)
1415 {
1416 log_amx("Connection failed in sqlv_read_all() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
1417
1418 return 0;
1419 }
1420
1421 bNewConnection = true;
1422 }
1423
1424 new szVaultName[32];
1425 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
1426
1427 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
1428 "SELECT `key`, `data`, `timestamp` FROM `%s`%s%s;",
1429 szVaultName);
1430
1431 new iReturn = 0;
1432
1433 if(!SQL_Execute(hQuery))
1434 {
1435 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
1436 log_amx("Error in sqlv_read_all(): %s", __SQLVAULT_ERROR);
1437 }
1438 else if((iReturn = SQL_NumResults(hQuery)))
1439 {
1440 new eVaultData[SQLVaultEntry];
1441
1442 while(SQL_MoreResults(hQuery))
1443 {
1444 SQL_ReadResult(hQuery, 0, eVaultData[SQLV_Key], charsmax(eVaultData[SQLV_Key]));
1445 SQL_ReadResult(hQuery, 1, eVaultData[SQLV_Data], charsmax(eVaultData[SQLV_Data]));
1446 eVaultData[SQLV_TimeStamp] = SQL_ReadResult(hQuery, 2);
1447
1448 ArrayPushArray(aVaultData, eVaultData);
1449
1450 SQL_NextRow(hQuery);
1451 }
1452 }
1453
1454 SQL_FreeHandle(hQuery);
1455
1456 if(bNewConnection)
1457 {
1458 SQL_FreeHandle(hConnection);
1459 }
1460
1461 return iReturn;
1462 }
1463
1464 /*
1465 * Reads a set of the vault data into an array
1466 *
1467 * @param hVault - The vault to read from
1468 * @param eOutputData - The array to store all of the selected set
1469 * @param iOutputSize - The size of the set to select
1470 * @param iStart - The offset of the vault to start at
1471 * @param szWhere - The where condition for selecting specific vault data (optional)
1472 * @param szSort - The method to sort the vault data by (optional)
1473 *
1474 * @return Returns the total number of vault entries
1475 *
1476 * @note The where condition is the same as the where clause from MySQL's SELECT statement.
1477 * Do not include "WHERE" inside the where clause.
1478 *
1479 * @note Sorting the vault data can be done 2 ways:
1480 * 1. Pass "asc" to sort in ascending order by the data value
1481 * Pass "desc" to sort in descending order by the data value
1482 * 2. Pass any other string to format the ORDER BY clause from MySQL
1483 * Do not include "ORDER BY" inside the sort string
1484 *
1485 * @note Example for grabbing top entries:
1486 *
1487 * new eVaultData[10][SQLVaultEntry];
1488 * new iVaultKeys = sqlv_read_set(hVault, eVaultData, sizeof(eVaultData), _, _, "desc");
1489 *
1490 * for(new i = 0; i < iVaultKeys; i++)
1491 * {
1492 * eVaultData[i][SQLV_Key] = key
1493 * eVaultData[i][SQLV_Data] = data
1494 * eVaultData[i][SQLV_TimeStamp] = timestamp
1495 * }
1496 *
1497 */
1498 SQLVAULT_FUNC_ATTRIB sqlv_read_set(SQLVault:hVault, eOutputData[][SQLVaultEntry], iOutputSize, iStart = 0, const szWhere[] = "", const szSort[] = "")
1499 {
1500 new szFixedWhere[256], szFixedSort[256];
1501
1502 if(szWhere[0])
1503 {
1504 formatex(szFixedWhere, charsmax(szFixedWhere), " WHERE %s", szWhere);
1505 }
1506
1507 if(szSort[0])
1508 {
1509 if(equali(szSort, "asc") || equali(szSort, "desc"))
1510 {
1511 formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY `data` %s", szSort);
1512 }
1513 else
1514 {
1515 formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY %s", szSort);
1516 }
1517 }
1518
1519 if(hVault == Invalid_SQLVault)
1520 {
1521 return 0;
1522 }
1523
1524 new Handle:hTuple;
1525 TrieGetCell(Trie:hVault, "tuple", hTuple);
1526
1527 if(hTuple == Empty_Handle)
1528 {
1529 return 0;
1530 }
1531
1532 new Handle:hConnection, bool:bNewConnection = false;
1533
1534 if(!TrieGetCell(Trie:hVault, "connection", hConnection))
1535 {
1536 hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
1537
1538 if(hConnection == Empty_Handle)
1539 {
1540 log_amx("Connection failed in sqlv_read_set() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
1541
1542 return 0;
1543 }
1544
1545 bNewConnection = true;
1546 }
1547
1548 new szVaultName[32];
1549 TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
1550
1551 new Handle:hQuery = SQL_PrepareQuery(hConnection,\
1552 "SELECT `key`, `data`, `timestamp` FROM `%s`%s%s LIMIT %d, %d;",
1553 szVaultName, szFixedWhere, szFixedSort, iStart, iOutputSize);
1554
1555 new iReturn = 0;
1556
1557 if(!SQL_Execute(hQuery))
1558 {
1559 SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
1560 log_amx("Error in sqlv_read_set(): %s", __SQLVAULT_ERROR);
1561 }
1562 else if(SQL_NumResults(hQuery))
1563 {
1564 while(iReturn < iOutputSize && SQL_MoreResults(hQuery))
1565 {
1566 SQL_ReadResult(hQuery, 0, eOutputData[iReturn][SQLV_Key], charsmax(eOutputData[][SQLV_Key]));
1567 SQL_ReadResult(hQuery, 1, eOutputData[iReturn][SQLV_Data], charsmax(eOutputData[][SQLV_Data]));
1568 eOutputData[iReturn][SQLV_TimeStamp] = SQL_ReadResult(hQuery, 2);
1569
1570 iReturn++;
1571
1572 SQL_NextRow(hQuery);
1573 }
1574 }
1575
1576 SQL_FreeHandle(hQuery);
1577
1578 if(bNewConnection)
1579 {
1580 SQL_FreeHandle(hConnection);
1581 }
1582
1583 return iReturn;
1584 }
1585
1586 /*
1587 * Makes a string safe to be held in the vault
1588 *
1589 * @param szString - The string to be made safe
1590 *
1591 * @return Returns the length of the string
1592 *
1593 * @note This overwrites the string's contents, so constants cannot be used.
1594 *
1595 */
1596 SQLVAULT_FUNC_ATTRIB QuoteString(szString[], cRemoveChar = ''')
1597 {
1598 new i, cChar;
1599
1600 while((cChar = szString[i]))
1601 {
1602 if(cChar == cRemoveChar)
1603 {
1604 szString[i] = 30;
1605 }
1606
1607 i++;
1608 }
1609
1610 return i;
1611 }
1612
1613 /*
1614 * Restores the strings original state after being used by QuoteString()
1615 *
1616 * @param szString - The string to be restored
1617 *
1618 * @return Returns the length of the string
1619 *
1620 * @note This overwrites the string's contents, so constants cannot be used.
1621 *
1622 */
1623 SQLVAULT_FUNC_ATTRIB UnQuoteString(szString[], cRemoveChar = ''')
1624 {
1625 new i, cChar;
1626
1627 while((cChar = szString[i]))
1628 {
1629 if(cChar == 30)
1630 {
1631 szString[i] = cRemoveChar;
1632 }
1633
1634 i++;
1635 }
1636
1637 return i;
1638 }
1639 /* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
1640 *{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang11274\\ f0\\ fs16 \n\\ par }
1641 */
1642