sqlitei.inc 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866
  1. /*
  2. SQLite Improved v0.9.7 by Slice
  3. Changelog:
  4. 2015-07-13:
  5. * Update for 0.3.7 R2.
  6. * All crash issues should be solved now, including the previous one that happened only on some servers.
  7. 2014-10-08:
  8. * Fix crash when using stmt_fetch_row on an empty result (only affects Linux servers).
  9. 2013-10-07:
  10. * Display errors from db_query. Works only on Windows.
  11. 2012-07-23:
  12. * Fix problem with persistent databases (hopefully).
  13. 2012-07-21:
  14. * Fix crash happening on Linux related to NULL values in db_free_result.
  15. 2012-07-15:
  16. * Improvements to persistent databases.
  17. 2012-06-15:
  18. * Fix compiler crash when db_query isn't used.
  19. 2012-05-27:
  20. * Always throw warnings when invalid results are given to SQLitei functions.
  21. * Even more improvements to stability!
  22. * GetAmxBase is now updated with a JIT compatible version (all credits to Zeex).
  23. * All the default DB functions (which are hooked by SQLitei) are now compatible with the JIT plugin.
  24. * Fixed a bug in SA-MP's SQLite implementation where strings would contain signed characters instead of unsigned.
  25. Most functions work just fine with both types of strings but strcmp, for one, does not.
  26. * stmt_bind_value now deals with packed strings properly.
  27. 2012-03-22:
  28. * db_query now accept extra parameters similar to those in stmt_bind_value, allowing
  29. a very quick way to format and run queries!
  30. 2012-03-21:
  31. * Fixed a rare crash that would occur if you closed a DB while having autofreed results open.
  32. * The deprecated db_query_autofree is now removed. Simply use db_query instead.
  33. * Fixed a problem where a certain integer would cause an invalid value.
  34. * Added DB::TYPE_UINT, which inserts an unsigned integer.
  35. An unsigned integer have values between 0 and 4294967295 as opposed to -2147483648 and 2147483647.
  36. * Added helper function db_print_query.
  37. * Added db_dump_table!
  38. 2012-03-01:
  39. * db_free_result will now completely ignore invalid results (0).
  40. 2012-02-12:
  41. * Added db_attach_memory_db and db_detach_memory_db.
  42. 2012-02-11:
  43. * Added DB::TYPE_ARRAY, which allows you to insert and read arrays with statements!
  44. * Improved error handling and increased some buffer sizes.
  45. * Added db_begin_transaction, db_end_transaction, and db_set_asynchronous.
  46. * Minor improvements here and there.
  47. 2012-02-10:
  48. * A few bug fixes.
  49. * Added db_field_is_null, which returns true if the field is a true NULL value (not just an empty string).
  50. * Deprecated db_query_autofree.
  51. 2012-02-09:
  52. * Defining WP_Hash prior to inclusion is no longer needed.
  53. * db_query now has an optional third argument - enable autorelease, which is
  54. true by default.
  55. * Improved stability on freeing results:
  56. - Freeing results twice will not crash the server anymore - it will just generate
  57. a warning.
  58. - Freeing a result that will be autoreleased will remove it from the autorelease pool.
  59. * The compiler will no longer wrongfully detect recursion inside this include.
  60. * Added db_query_int and db_query_float.
  61. * Added db_get_struct_info and db_set_struct_info; used mainly internally.
  62. * Added db_exec and db_insert.
  63. * Performance improvements!
  64. 2012-02-08:
  65. * db_print_result will no longer go to the end of the result.
  66. * Added db_get_row_index, db_set_row_index, and db_rewind.
  67. 2012-02-07:
  68. * db_get_field/db_get_field_assoc will not crash anymore with NULL values!
  69. 2011-12-21:
  70. * Added two new types for stmt_bind_value:
  71. - DB::TYPE_WP_HASH: Puts a BLOB value of a whirlpool hash from the given string into the query (ex. x'FFAA4411...').
  72. - DB::TYPE_PLAYER_NAME: Puts a player name from the ID passed.
  73. Note that DB_USE_WHIRLPOOL must be defined as true in order for DB::TYPE_WP_HASH to work.
  74. * Made some optimizations and minor bug fixes.
  75. * stmt_execute will now autofree the result unless the 3rd argument is false.
  76. * Added the preprocessor options DE_DEBUG (logs debug info) and DB_LOG_TO_CHAT (prints log messages to chat).
  77. * Improved the way results are dealt with internally to avoid crashes at all costs.
  78. * Added debug messages pretty much everywhere.
  79. 2011-12-16:
  80. * Added db_open_persistent, db_is_persistent, db_is_valid_persistent, and db_free_persistent.
  81. * Added db_query_autofree.
  82. * Added db_get_field_int and db_get_field_float.
  83. * Corrected a few SQLite natives.
  84. 2011-12-15:
  85. * Added stmt_autoclose.
  86. * Memory usage decreased significantly.
  87. * All functions now accept both packed and unpacked strings.
  88. * Minor bug fixes and optimizations.
  89. 2011-12-14:
  90. * Initial release.
  91. */
  92. #if !defined _samp_included
  93. #error Please include a_samp before sqlitei.
  94. #endif
  95. #if defined __fmt_funcinc && defined FormatSpecifier
  96. #error Please include sqlitei before formatex.
  97. #endif
  98. #if !defined HTTP
  99. #tryinclude <a_http>
  100. #endif
  101. #if !defined DB_MAX_PARAMS
  102. #define DB_MAX_PARAMS 32
  103. #endif
  104. #if !defined DB_MAX_STATEMENTS
  105. #define DB_MAX_STATEMENTS 16
  106. #endif
  107. #if !defined DB_MAX_STATEMENT_SIZE
  108. #define DB_MAX_STATEMENT_SIZE 1024
  109. #endif
  110. #if !defined DB_MAX_FIELDS
  111. #define DB_MAX_FIELDS 64
  112. #endif
  113. #if !defined DB_MAX_PERSISTENT_DATABASES
  114. #define DB_MAX_PERSISTENT_DATABASES 4
  115. #endif
  116. #if !defined DB_USE_WHIRLPOOL
  117. #define DB_USE_WHIRLPOOL false
  118. #endif
  119. #if !defined DB_DEBUG
  120. #define DB_DEBUG false
  121. #endif
  122. #if !defined DB_DEBUG_BACKTRACE_NOTICE
  123. #define DB_DEBUG_BACKTRACE_NOTICE false
  124. #endif
  125. #if !defined DB_DEBUG_BACKTRACE_WARNING
  126. #define DB_DEBUG_BACKTRACE_WARNING false
  127. #endif
  128. #if !defined DB_DEBUG_BACKTRACE_ERROR
  129. #define DB_DEBUG_BACKTRACE_ERROR false
  130. #endif
  131. #if !defined DB_DEBUG_BACKTRACE_DEBUG
  132. #define DB_DEBUG_BACKTRACE_DEBUG false
  133. #endif
  134. #if !defined DB_LOG_TO_CHAT
  135. #define DB_LOG_TO_CHAT false
  136. #endif
  137. // "Namespace"
  138. #define DB:: DB_
  139. // Fix some natives ("const" keyword was missing)
  140. native DB:db_open@(const szName[]) = db_open;
  141. native DBResult:db_query@(DB:db, const szQuery[]) = db_query;
  142. native db_get_field@(DBResult:dbresult, field, result[], maxlength) = db_get_field;
  143. native db_get_field_assoc@(DBResult:dbresult, const field[], result[], maxlength) = db_get_field_assoc;
  144. native db_close@(DB:db) = db_close;
  145. native db_free_result@(DBResult:dbrResult) = db_free_result;
  146. #define db_open db_open@
  147. #define db_query%1( db_query_hook(_,
  148. #define db_close db_close_hook
  149. #define db_free_result db_free_result_hook
  150. #if DB::USE_WHIRLPOOL
  151. native DB::WP_Hash(buffer[], len, const str[]) = WP_Hash;
  152. #endif
  153. enum DB::e_SYNCHRONOUS_MODE {
  154. DB::SYNCHRONOUS_OFF,
  155. DB::SYNCHRONOUS_NORMAL,
  156. DB::SYNCHRONOUS_FULL
  157. };
  158. enum DBDataType: {
  159. DB::TYPE_NONE,
  160. DB::TYPE_NULL,
  161. DB::TYPE_INT,
  162. DB::TYPE_INTEGER = DB::TYPE_INT,
  163. DB::TYPE_UINT,
  164. DB::TYPE_UINTEGER = DB::TYPE_UINT,
  165. DB::TYPE_FLOAT,
  166. DB::TYPE_STRING,
  167. DB::TYPE_RAW_STRING,
  168. DB::TYPE_IDENTIFIER,
  169. // Special types
  170. #if DB::USE_WHIRLPOOL
  171. DB::TYPE_WP_HASH,
  172. #endif
  173. DB::TYPE_PLAYER_NAME,
  174. DB::TYPE_PLAYER_IP,
  175. DB::TYPE_ARRAY
  176. };
  177. #define INT: DB::TYPE_INT,QQPA:
  178. #define INTEGER: DB::TYPE_INT,QQPA:
  179. #define UINT: DB::TYPE_UINT,QQPA:
  180. #define UINTEGER: DB::TYPE_UINT,QQPA:
  181. #define FLOAT: DB::TYPE_FLOAT,QQPA:
  182. #define STRING: DB::TYPE_STRING,QQPA:
  183. #define RAW_STRING: DB::TYPE_RAW_STRING,QQPA:
  184. #define IDENTIFIER: DB::TYPE_IDENTIFIER,QQPA:
  185. #if DB::USE_WHIRLPOOL
  186. #define WP_HASH: DB::TYPE_WP_HASH,QQPA:
  187. #endif
  188. #define PLAYER_NAME: DB::TYPE_PLAYER_NAME,QQPA:
  189. #define PLAYER_IP: DB::TYPE_PLAYER_IP,QQPA:
  190. enum DB::E_STATEMENT {
  191. // The ready-to-run query.
  192. e_szQuery[DB::MAX_STATEMENT_SIZE + 1],
  193. // Parameter count
  194. e_iParams,
  195. // The parameter types.
  196. DBDataType:e_aiParamTypes[DB::MAX_PARAMS],
  197. // Position of parameters in the query string.
  198. e_aiParamPositions[DB::MAX_PARAMS],
  199. // Length of parameters in the query string.
  200. e_aiParamLengths[DB::MAX_PARAMS],
  201. // Types of bound return fields
  202. DBDataType:e_aiFieldTypes[DB::MAX_FIELDS],
  203. // Sizes of bound result fields (used only for strings currently)
  204. e_aiFieldSizes[DB::MAX_FIELDS],
  205. // Addresses of bound result fields
  206. e_aiFieldAddresses[DB::MAX_FIELDS],
  207. // The database it was created for
  208. DB:e_dbDatabase,
  209. // The result (after executing)
  210. DBResult:e_dbrResult,
  211. // How many rows were fetched from the most recent result
  212. e_iFetchedRows,
  213. // Whether or not any leftover results should be automatically freed
  214. // Note that whenever a new result is put into e_dbrResult, the previous one is freed.
  215. bool:e_bAutoFreeResult
  216. };
  217. enum {
  218. SQLITE_LIMIT_LENGTH,
  219. SQLITE_LIMIT_SQL_LENGTH,
  220. SQLITE_LIMIT_COLUMN,
  221. SQLITE_LIMIT_EXPR_DEPTH,
  222. SQLITE_LIMIT_COMPOUND_SELECT,
  223. SQLITE_LIMIT_VDBE_OP,
  224. SQLITE_LIMIT_FUNCTION_ARG,
  225. SQLITE_LIMIT_ATTACHED,
  226. SQLITE_LIMIT_LIKE_PATTERN_LEN,
  227. SQLITE_LIMIT_VARIABLE_NUMBER,
  228. SQLITE_LIMIT_TRIGGER_DEPTH
  229. };
  230. // SQLite 3 C-struct offsets
  231. enum e_SQLITE3 {
  232. sqlite3_pVfs [4],
  233. sqlite3_iBackends [4],
  234. sqlite3_pBackends [4],
  235. sqlite3_iFlags [4],
  236. sqlite3_iOpenFlags [4],
  237. sqlite3_iErrorCode [4],
  238. sqlite3_iErrorMask [4],
  239. bool:sqlite3_bAutoCommit [1],
  240. sqlite3_iTempStore [1],
  241. bool:sqlite3_bMallocFailed [1],
  242. sqlite3_iDefaultLockMode [1],
  243. sqlite3_iNextAutovac [1],
  244. bool:sqlite3_bSuppressErrors [1],
  245. sqlite3_iPad [2],
  246. sqlite3_iNextPagesize [4],
  247. sqlite3_iNumTables [4],
  248. sqlite3_pDefaultCollation [4],
  249. sqlite3_iLastRowid [4],
  250. sqlite3_iLastRowidUpperBytes[4],
  251. sqlite3_iMagic [4],
  252. sqlite3_iNumChanges [4],
  253. sqlite3_iNumTotalChanges [4],
  254. sqlite3_aiLimits [SQLITE_LIMIT_TRIGGER_DEPTH * 4],
  255. sqlite3_aInitInfo [12],
  256. sqlite3_iNumExtensions [4],
  257. sqlite3_pExtensions [4],
  258. sqlite3_pVdbe [4],
  259. sqlite3_iActiveVdbeCount [4],
  260. sqlite3_iWritingVdbeCount [4],
  261. sqlite3_pTraceFunc [4],
  262. sqlite3_pTraceArg [4],
  263. sqlite3_pProfilingFunc [4],
  264. sqlite3_pProfilingArg [4],
  265. sqlite3_pCommitArg [4],
  266. sqlite3_pCommitCallback [4],
  267. sqlite3_pRollbackArg [4],
  268. sqlite3_pRollbackCallback [4],
  269. sqlite3_pUpdateArg [4],
  270. sqlite3_pUpdateCallback [4],
  271. sqlite3_pWalCallback [4],
  272. sqlite3_pWalArg [4],
  273. sqlite3_pCollNeeded [4],
  274. sqlite3_pCollNeeded16 [4],
  275. sqlite3_pCollNeededArg [4],
  276. sqlite3_pError [4],
  277. sqlite3_pErrorMsg [4],
  278. sqlite3_pErrorMsg16 [4]
  279. };
  280. enum DB::E_PERSISTENT_DB {
  281. e_szName[128 char],
  282. bool:e_bIsUsed,
  283. DB:e_dbDatabase
  284. };
  285. static stock
  286. gs_szBuffer[8192],
  287. gs_aiCompressBuffer[3072],
  288. gs_Statements[DBStatement:DB::MAX_STATEMENTS][DB::E_STATEMENT],
  289. gs_iAutoFreeTimer = -1,
  290. gs_iAutoFreeResultsIndex = 0,
  291. DBResult:gs_adbrAutoFreeResults[1024],
  292. gs_iAutoCloseStatementsIndex = 0,
  293. DBStatement:gs_astAutoCloseStatements[1024],
  294. gs_PersistentDatabases[DB::MAX_PERSISTENT_DATABASES][DB::E_PERSISTENT_DB],
  295. gs_iClosePersistentTimer = -1,
  296. gs_iFreeStatementResultsTimer = -1,
  297. gs_szNull[1] = {0}
  298. ;
  299. const
  300. DBStatement:DB::INVALID_STATEMENT = DBStatement:-1,
  301. DBResult:DB::INVALID_RESULT = DBResult:0
  302. ;
  303. #if !DB_DEBUG
  304. #define DB_Debug(%1);
  305. #endif
  306. #if !DB_LOG_TO_CHAT
  307. #if DB_DEBUG_BACKTRACE_NOTICE
  308. #define DB_Notice(%1) print(!"SQLitei Notice: " %1),PrintAmxBacktrace()
  309. #define DB_Noticef(%1) printf("SQLitei Notice: " %1),PrintAmxBacktrace()
  310. #else
  311. #define DB_Notice(%1) print(!"SQLitei Notice: " %1)
  312. #define DB_Noticef(%1) printf("SQLitei Notice: " %1)
  313. #endif
  314. #if DB_DEBUG_BACKTRACE_WARNING
  315. #define DB_Warning(%1) print(!"SQLitei Warning: " %1),PrintAmxBacktrace()
  316. #define DB_Warningf(%1) printf("SQLitei Warning: " %1),PrintAmxBacktrace()
  317. #else
  318. #define DB_Warning(%1) print(!"SQLitei Warning: " %1)
  319. #define DB_Warningf(%1) printf("SQLitei Warning: " %1)
  320. #endif
  321. #if DB_DEBUG_BACKTRACE_ERROR
  322. #define DB_Error(%1) print(!"SQLitei Error: " %1),PrintAmxBacktrace()
  323. #define DB_Errorf(%1) printf("SQLitei Error: " %1),PrintAmxBacktrace()
  324. #else
  325. #define DB_Error(%1) print(!"SQLitei Error: " %1)
  326. #define DB_Errorf(%1) printf("SQLitei Error: " %1)
  327. #endif
  328. #if DB_DEBUG
  329. #if DB_DEBUG_BACKTRACE_DEBUG
  330. #define DB_Debug(%1) printf("SQLitei Debug: " %1),PrintAmxBacktrace()
  331. #else
  332. #define DB_Debug(%1) printf("SQLitei Debug: " %1)
  333. #endif
  334. #endif
  335. #else
  336. new
  337. gs_szLogMessageBuffer[256]
  338. ;
  339. #define DB_Notice(%1) SendClientMessageToAll(0xFFFFFFFF, "SQLitei Notice: " %1), print(!"SQLitei Notice: " %1)
  340. #define DB_Warning(%1) SendClientMessageToAll(0xEBBD17FF, "SQLitei Warning: " %1), print(!"SQLitei Warning: " %1)
  341. #define DB_Error(%1) SendClientMessageToAll(0xCC0000FF, "SQLitei Error: " %1), print(!"SQLitei Error: " %1)
  342. #define DB_Noticef(%1) format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Notice: " %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xDDDDDDFF, gs_szLogMessageBuffer)
  343. #define DB_Warningf(%1) format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Warning: " %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xEBBD17FF, gs_szLogMessageBuffer)
  344. #define DB_Errorf(%1) format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Error: " %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xCC0000FF, gs_szLogMessageBuffer)
  345. #if DB_DEBUG
  346. #define DB_Debug(%1) format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Debug: " %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xFFFFFFFF, gs_szLogMessageBuffer)
  347. #endif
  348. #endif
  349. // Has to be defined after statement functions.
  350. stock DBResult:db_query_hook(iTagOf3 = tagof(_bAutoRelease), DB:db, const szQuery[], {bool, DBDataType}:_bAutoRelease = true, {DBDataType, QQPA}:...);
  351. // forward's
  352. forward bool:db_set_row_index(DBResult:dbrResult, iRow);
  353. forward bool:db_free_result_hook(DBResult:dbrResult);
  354. forward bool:db_set_synchronous(DB:db, DB::e_SYNCHRONOUS_MODE:iValue);
  355. forward DB::funcinc();
  356. public DB::funcinc() {
  357. strcat(gs_szBuffer, "");
  358. strpack(gs_szBuffer, "");
  359. ispacked(gs_szBuffer);
  360. db_get_field(DBResult:0, 0, gs_szBuffer, 0);
  361. db_query(DB:0,"");
  362. }
  363. static stock DB::CompressArray(const aiArray[], iSize = sizeof(aiArray), aiOutput[]) {
  364. new
  365. iOutputIndex = 4,
  366. iValue,
  367. iMSB,
  368. iShift
  369. ;
  370. // * 0b11000000 = Single byte, negative
  371. // * 0b10000000 = Single byte
  372. // * 0b01000000 = Multi-byte
  373. // - 0b01000000 = More bytes
  374. // - 0b11000000 = Last byte
  375. // - 0b10000000 = Unused
  376. for (new i = 0; i < iSize; i++) {
  377. // Will the value fit in one byte?
  378. iValue = aiArray[i];
  379. if (-0b00111111 <= iValue <= 0b00111111) {
  380. // Is the value negative?
  381. if (iValue & 0x80000000) {
  382. // Set the "single byte, negative" bits on and put the value without its sign
  383. aiOutput{iOutputIndex++} = 0b11000000 | -iValue;
  384. } else {
  385. // Just put the value in with the "single byte" bit
  386. aiOutput{iOutputIndex++} = 0b10000000 | iValue;
  387. }
  388. } else {
  389. // Figure out how many bits we'll have to write
  390. iMSB = DB::FindMSB(iValue) + 1;
  391. // Make iShift a multiple of 6 (if it isn't already)
  392. if ((iShift = iMSB % 6))
  393. aiOutput{iOutputIndex++} = 0b01000000 | (iValue >>> (iMSB - iShift) & ~(0xFFFFFFFF << iShift));
  394. iShift = iMSB - iShift;
  395. // Write bits out left-right
  396. while ((iShift -= 6) >= 0)
  397. aiOutput{iOutputIndex++} = 0b01000000 | (iValue >>> iShift & 0b00111111);
  398. // Change the "more bytes" bits into "last byte"
  399. aiOutput{iOutputIndex - 1} |= 0b11000000;
  400. }
  401. }
  402. // Put the number of bytes we just wrote into the first cell of the output
  403. aiOutput[0] = 0x80808080 | ((iOutputIndex & 0x1FE00000) << 3) | ((iOutputIndex & 0x3FC000) << 2) | ((iOutputIndex & 0x7F80) << 1) | (iOutputIndex & 0x7F);
  404. // Make sure the bytes in the last cell are 0
  405. aiOutput{iOutputIndex} = 0;
  406. iValue = iOutputIndex;
  407. while (++iOutputIndex % 4)
  408. aiOutput{iOutputIndex} = 0;
  409. // Return the number of bytes written (not counting the first 4)
  410. return iValue;
  411. }
  412. static stock DB::DecompressArray(const aiCompressedArray[], aiOutput[], iOutputSize = sizeof(aiOutput)) {
  413. new
  414. iBytes,
  415. iOutputIndex = 0
  416. ;
  417. // Get the number of bytes to parse
  418. iBytes = aiCompressedArray[0];
  419. iBytes = ((iBytes & 0x7F000000) >>> 3) | ((iBytes & 0x7F0000) >>> 2) | ((iBytes & 0x7F00) >>> 1) | (iBytes & 0x7F);
  420. for (new i = 4; i < iBytes; i++) {
  421. // Out of slots?
  422. if (iOutputIndex >= iOutputSize) {
  423. DB::Error("(DB::DecompressArray) Compressed array is larger than decompress buffer.");
  424. break;
  425. }
  426. // Single byte?
  427. if ((aiCompressedArray{i} & 0b10000000)) {
  428. // Negative?
  429. if ((aiCompressedArray{i} & 0b01000000))
  430. aiOutput[iOutputIndex++] = -(aiCompressedArray{i} & 0b00111111);
  431. else
  432. aiOutput[iOutputIndex++] = (aiCompressedArray{i} & 0b00111111);
  433. } else {
  434. // Multi byte; read the last bits
  435. aiOutput[iOutputIndex] = aiCompressedArray{i} & 0b00111111;
  436. // Keep reading bits while shifting the value to the left
  437. do {
  438. aiOutput[iOutputIndex] <<= 6;
  439. aiOutput[iOutputIndex] |= aiCompressedArray{++i} & 0b00111111;
  440. } while ((aiCompressedArray{i} & 0b10000000) == 0);
  441. iOutputIndex++;
  442. }
  443. }
  444. return iOutputIndex;
  445. }
  446. static stock DB::memset(aArray[], iValue, iSize = sizeof(aArray)) {
  447. new
  448. iAddress
  449. ;
  450. // Store the address of the array
  451. #emit LOAD.S.pri 12
  452. #emit STOR.S.pri iAddress
  453. // Convert the size from cells to bytes
  454. iSize *= 4;
  455. // Loop until there is nothing more to fill
  456. while (iSize > 0) {
  457. // I have to do this because the FILL instruction doesn't accept a dynamic number.
  458. if (iSize >= 4096) {
  459. #emit LOAD.S.alt iAddress
  460. #emit LOAD.S.pri iValue
  461. #emit FILL 4096
  462. iSize -= 4096;
  463. iAddress += 4096;
  464. } else if (iSize >= 1024) {
  465. #emit LOAD.S.alt iAddress
  466. #emit LOAD.S.pri iValue
  467. #emit FILL 1024
  468. iSize -= 1024;
  469. iAddress += 1024;
  470. } else if (iSize >= 256) {
  471. #emit LOAD.S.alt iAddress
  472. #emit LOAD.S.pri iValue
  473. #emit FILL 256
  474. iSize -= 256;
  475. iAddress += 256;
  476. } else if (iSize >= 64) {
  477. #emit LOAD.S.alt iAddress
  478. #emit LOAD.S.pri iValue
  479. #emit FILL 64
  480. iSize -= 64;
  481. iAddress += 64;
  482. } else if (iSize >= 16) {
  483. #emit LOAD.S.alt iAddress
  484. #emit LOAD.S.pri iValue
  485. #emit FILL 16
  486. iSize -= 16;
  487. iAddress += 16;
  488. } else {
  489. #emit LOAD.S.alt iAddress
  490. #emit LOAD.S.pri iValue
  491. #emit FILL 4
  492. iSize -= 4;
  493. iAddress += 4;
  494. }
  495. }
  496. // aArray is used, just not by its symbol name
  497. #pragma unused aArray
  498. return 1;
  499. }
  500. stock DB::LazyInitialize() {
  501. static
  502. bool:bIsInitialized = false
  503. ;
  504. if (bIsInitialized)
  505. return;
  506. bIsInitialized = true;
  507. #if defined HTTP
  508. HTTP(0x7FEDCBA0, HTTP_GET, !"spelsajten.net/sqlitei_version.php?version=097", "", !"DB_VersionCheckReponse");
  509. #endif
  510. }
  511. #if defined HTTP
  512. forward DB::VersionCheckReponse(iIndex, iResponseCode, const szResponse[]);
  513. public DB::VersionCheckReponse(iIndex, iResponseCode, const szResponse[]) {
  514. if (iResponseCode == 200) {
  515. if (strval(szResponse) != 1) {
  516. print(!"\n\n\n *******************************************************************");
  517. print( !" * There's a new version version of SQLite Improved available! *");
  518. print( !" * Please visit the topic at the SA-MP forums for the latest copy. *");
  519. print( !" * Alternatively, get it here: http://spelsajten.net/sqlitei.inc *");
  520. print( !" *******************************************************************\n\n\n");
  521. }
  522. }
  523. }
  524. #endif
  525. stock db_escape_string(szString[], const szEnclosing[] = "'", iSize = sizeof(szString)) {
  526. DB::LazyInitialize();
  527. new
  528. iPos
  529. ;
  530. while (-1 != (iPos = strfind(szString, szEnclosing, _, iPos))) {
  531. strins(szString, szEnclosing, iPos, iSize);
  532. iPos += 2;
  533. }
  534. }
  535. stock bool:db_is_persistent(DB:db) {
  536. return !!(_:db & 0x80000000);
  537. }
  538. stock bool:db_is_valid_persistent(DB:db) {
  539. new
  540. iIndex = (_:db & 0x7FFFFFFF)
  541. ;
  542. if ((0 <= iIndex < sizeof(gs_PersistentDatabases)) && gs_PersistentDatabases[iIndex][e_bIsUsed])
  543. return true;
  544. return false;
  545. }
  546. stock bool:db_is_table_exists(DB:db, const szTable[])
  547. {
  548. new
  549. DBResult:dbrResult
  550. ;
  551. format(gs_szBuffer, sizeof(gs_szBuffer), "SELECT name FROM sqlite_master WHERE type = 'table' AND tbl_name = '%s'", szTable);
  552. dbrResult = db_query(db, gs_szBuffer, false);
  553. if (db_num_fields(dbrResult)) {
  554. db_free_result(dbrResult);
  555. return true;
  556. }
  557. db_free_result(dbrResult);
  558. return false;
  559. }
  560. stock bool:db_rewind(DBResult:dbrResult) {
  561. if (dbrResult == DB::INVALID_RESULT) {
  562. DB::Notice("(db_rewind) Invalid result given.");
  563. return false;
  564. }
  565. return db_set_row_index(dbrResult, 0);
  566. }
  567. stock bool:db_exec(DB:db, const szQuery[]) {
  568. new
  569. DBResult:dbrResult = db_query(db, szQuery, false)
  570. ;
  571. if (dbrResult) {
  572. db_free_result(dbrResult);
  573. return true;
  574. }
  575. return false;
  576. }
  577. stock db_insert(DB:db, const szQuery[]) {
  578. new
  579. DBResult:dbrResult = db_query(db, szQuery, false)
  580. ;
  581. if (dbrResult) {
  582. db_free_result(dbrResult);
  583. return db_last_insert_rowid(db);
  584. }
  585. return 0;
  586. }
  587. stock db_get_struct_info(DB:db, {_, e_SQLITE3}:iOffset) {
  588. if (db_is_persistent(db)) {
  589. if (!db_is_valid_persistent(db)) {
  590. DB::Errorf("(db_get_struct_info) Invalid persistent database given (%04x%04x).", _:db >>> 16, _:db & 0xFFFF);
  591. return 0;
  592. }
  593. new iIndex = (_:db & 0x7FFFFFFF);
  594. db = gs_PersistentDatabases[iIndex][e_dbDatabase];
  595. if (!db) {
  596. DB::Errorf("(db_get_struct_info) Closed persistent database given (%04x%04x).", _:db >>> 16, _:db & 0xFFFF);
  597. return 0;
  598. }
  599. }
  600. new
  601. iAddress = db_get_mem_handle(db & DB:0x7FFFFFFF) - DB::GetAmxBaseRelative() + iOffset,
  602. iValue
  603. ;
  604. #emit LREF.S.pri iAddress
  605. #emit STOR.S.pri iValue
  606. return iValue;
  607. }
  608. stock db_set_struct_info(DB:db, {_, e_SQLITE3}:iOffset, iValue) {
  609. if (db_is_persistent(db)) {
  610. if (!db_is_valid_persistent(db)) {
  611. DB::Errorf("(db_set_struct_info) Invalid persistent database given (%04x%04x).", _:db >>> 16, _:db & 0xFFFF);
  612. return 0;
  613. }
  614. new iIndex = (_:db & 0x7FFFFFFF);
  615. db = gs_PersistentDatabases[iIndex][e_dbDatabase];
  616. if (!db) {
  617. DB::Errorf("(db_set_struct_info) Closed persistent database given (%04x%04x).", _:db >>> 16, _:db & 0xFFFF);
  618. return 0;
  619. }
  620. }
  621. new
  622. iAddress = db_get_mem_handle(db & DB:0x7FFFFFFF) - DB::GetAmxBaseRelative() + iOffset
  623. ;
  624. #emit LOAD.S.pri iValue
  625. #emit SREF.S.pri iAddress
  626. }
  627. stock bool:db_set_row_index(DBResult:dbrResult, iRow) {
  628. if (dbrResult == DB::INVALID_RESULT) {
  629. DB::Notice("(db_set_row_index) Invalid result given.");
  630. return false;
  631. }
  632. if (iRow < 0 || iRow >= db_num_rows(dbrResult))
  633. return false;
  634. new
  635. iAddress = db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative() + 16
  636. ;
  637. #emit LOAD.S.pri iRow
  638. #emit SREF.S.pri iAddress
  639. return true;
  640. }
  641. stock db_get_row_index(DBResult:dbrResult) {
  642. if (dbrResult == DB::INVALID_RESULT) {
  643. DB::Notice("(db_get_row_index) Invalid result given.");
  644. return 0;
  645. }
  646. new
  647. iAddress = db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative() + 16
  648. ;
  649. #emit LREF.S.pri iAddress
  650. #emit STACK 4
  651. #emit RETN
  652. return 0;
  653. }
  654. stock DB:db_open_persistent(const szName[]) {
  655. new
  656. DB:db,
  657. iIndex = -1
  658. ;
  659. for (new i = 0; i < sizeof(gs_PersistentDatabases); i++) {
  660. if (!gs_PersistentDatabases[i][e_bIsUsed]) {
  661. iIndex = i;
  662. break;
  663. }
  664. }
  665. if (iIndex == -1) {
  666. DB::Error("(db_open_persistent) Unable to find a free slot.");
  667. return DB:-1;
  668. }
  669. if (!(db = db_open(szName))) {
  670. DB::Error("(db_open_persistent) Unable to open the database.");
  671. return DB:-1;
  672. }
  673. gs_PersistentDatabases[iIndex][e_bIsUsed] = true;
  674. gs_PersistentDatabases[iIndex][e_dbDatabase] = db;
  675. gs_PersistentDatabases[iIndex][e_szName][0] = 0;
  676. if (gs_iClosePersistentTimer == -1)
  677. gs_iClosePersistentTimer = SetTimer("db_close_persistent", 0, false);
  678. strpack(gs_PersistentDatabases[iIndex][e_szName], szName, _:e_bIsUsed);
  679. DB::Debug("(db_open_persistent=%d) Opened new persistent DB.", iIndex);
  680. return DB:(iIndex | 0x80000000);
  681. }
  682. stock db_close_hook(DB:db) {
  683. new
  684. iIndex
  685. ;
  686. if (db_is_persistent(db)) {
  687. if (!db_is_valid_persistent(db)) {
  688. DB::Errorf("(db_close) Invalid persistent database given (%04x%04x).", _:db >>> 16, _:db & 0xFFFF);
  689. return;
  690. }
  691. iIndex = (_:db & 0x7FFFFFFF);
  692. if (gs_PersistentDatabases[iIndex][e_dbDatabase]) {
  693. db_close@(gs_PersistentDatabases[iIndex][e_dbDatabase]);
  694. gs_PersistentDatabases[iIndex][e_dbDatabase] = DB:0;
  695. DB::Debug("(db_close) Closed the DB for the persistent DB with index %d.", iIndex);
  696. } else {
  697. DB::Debug("(db_close) Would close the DB for the persistent DB with index %d, but it already is.", iIndex);
  698. }
  699. } else {
  700. db_close@(db);
  701. }
  702. }
  703. stock db_query_int(DB:db, const szQuery[], iField = 0) {
  704. new
  705. DBResult:dbrResult = db_query(db, szQuery, false)
  706. ;
  707. if (!dbrResult) {
  708. strunpack(gs_szBuffer, szQuery);
  709. DB::Warningf("(db_query_int) Query failed: \"%s\".", gs_szBuffer);
  710. return 0;
  711. }
  712. db_get_field(dbrResult, iField, gs_szBuffer, sizeof(gs_szBuffer) - 1);
  713. db_free_result(dbrResult);
  714. return strval(gs_szBuffer);
  715. }
  716. stock Float:db_query_float(DB:db, const szQuery[], iField = 0) {
  717. new
  718. DBResult:dbrResult = db_query(db, szQuery, false)
  719. ;
  720. if (!dbrResult) {
  721. strunpack(gs_szBuffer, szQuery);
  722. DB::Warningf("(db_query_float) Query failed: \"%s\".", gs_szBuffer);
  723. return 0.0;
  724. }
  725. db_get_field(dbrResult, iField, gs_szBuffer, sizeof(gs_szBuffer) - 1);
  726. db_free_result(dbrResult);
  727. return floatstr(gs_szBuffer);
  728. }
  729. stock db_is_result_freed(DBResult:dbrResult) {
  730. if (dbrResult == DB::INVALID_RESULT) {
  731. DB::Notice("(db_is_result_freed) Invalid result given.");
  732. return true;
  733. }
  734. return db_get_result_mem_handle(dbrResult) == 0;
  735. }
  736. stock bool:db_free_result_hook(DBResult:dbrResult) {
  737. if (dbrResult == DB::INVALID_RESULT) {
  738. DB::Notice("(db_free_result_hook) Invalid result given.");
  739. return false;
  740. }
  741. DB::Debug("(db_free_result) Freeing 0x%04x%04x.", _:dbrResult >>> 16, _:dbrResult & 0xFFFF);
  742. for (new i = gs_iAutoFreeResultsIndex; i--; ) {
  743. if (gs_adbrAutoFreeResults[i] == dbrResult) {
  744. gs_adbrAutoFreeResults[i] = DBResult:0;
  745. DB::Debug("(db_free_result) The result being freed was inside the autorelease pool.");
  746. }
  747. }
  748. new
  749. iFreeTestAddress = db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative() + 16,
  750. iData
  751. ;
  752. #emit LREF.S.pri iFreeTestAddress
  753. #emit STOR.S.pri iData
  754. if (iData != 0xFFFFFFFF) {
  755. new
  756. iResultAddress = db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative(),
  757. iAddress,
  758. iRows,
  759. iCols,
  760. iDataAddress,
  761. iOffset,
  762. iNullAddress
  763. ;
  764. #emit CONST.pri gs_szNull
  765. #emit STOR.S.pri iNullAddress
  766. iNullAddress += DB::GetAmxBaseRelative();
  767. iAddress = iResultAddress;
  768. #emit LREF.S.pri iAddress
  769. #emit STOR.S.pri iRows
  770. iAddress += 4;
  771. #emit LREF.S.pri iAddress
  772. #emit STOR.S.pri iCols
  773. iAddress += 4;
  774. #emit LREF.S.pri iAddress
  775. #emit STOR.S.pri iDataAddress
  776. iDataAddress -= DB::GetAmxBaseRelative();
  777. iOffset = (iCols + iRows * iCols) * 4 - 4;
  778. while (iOffset >= 0) {
  779. iAddress = iDataAddress + iOffset;
  780. #emit LREF.S.pri iAddress
  781. #emit STOR.S.pri iAddress
  782. if (iAddress == iNullAddress) {
  783. iAddress = iDataAddress + iOffset;
  784. #emit CONST.pri 0
  785. #emit SREF.S.pri iAddress
  786. }
  787. iOffset -= 4;
  788. }
  789. db_free_result@(dbrResult);
  790. #emit CONST.pri 0xFFFFFFFF
  791. #emit SREF.S.pri iFreeTestAddress
  792. return true;
  793. } else {
  794. DB::Warning("(db_free_result) Attempted to free an already freed result; crash prevented.");
  795. }
  796. return false;
  797. }
  798. stock db_free_persistent(DB:db) {
  799. new
  800. iIndex
  801. ;
  802. if (!db_is_valid_persistent(db)) {
  803. DB::Errorf("(db_free_persistent) Invalid persistent database given (%04x%04x).", _:db >>> 16, _:db & 0xFFFF);
  804. return;
  805. }
  806. iIndex = (_:db & 0x7FFFFFFF);
  807. if (gs_PersistentDatabases[iIndex][e_dbDatabase]) {
  808. db_close@(gs_PersistentDatabases[iIndex][e_dbDatabase]);
  809. gs_PersistentDatabases[iIndex][e_dbDatabase] = DB:0;
  810. DB::Debug("(db_free_persistent:%d) Closed and freed the persistent DB.", iIndex);
  811. } else {
  812. DB::Debug("(db_free_persistent:%d) Freed the already closed persistent DB.", iIndex);
  813. }
  814. gs_PersistentDatabases[iIndex][e_bIsUsed] = false;
  815. }
  816. stock db_changes(DB:db) {
  817. DB::LazyInitialize();
  818. if (!db) {
  819. DB::Error("(db_changes) Invalid database handle given.");
  820. return 0;
  821. }
  822. return db_get_struct_info(db, sqlite3_iNumChanges);
  823. }
  824. stock db_begin_transaction(DB:db)
  825. return db_exec(db, !"BEGIN");
  826. stock db_end_transaction(DB:db)
  827. return db_exec(db, !"COMMIT");
  828. stock db_set_asynchronous(DB:db, bool:bSet = true) {
  829. db_set_synchronous(DB:db, bSet ? DB::SYNCHRONOUS_OFF : DB::SYNCHRONOUS_FULL);
  830. }
  831. stock bool:db_set_synchronous(DB:db, DB::e_SYNCHRONOUS_MODE:iValue) {
  832. if (0 <= _:iValue <= 2) {
  833. format(gs_szBuffer, sizeof(gs_szBuffer), "PRAGMA synchronous = %d", _:iValue);
  834. return db_exec(db, gs_szBuffer);
  835. } else
  836. return false;
  837. }
  838. stock bool:db_attach_memory_db(DB:db, const szName[]) {
  839. strunpack(gs_szBuffer, szName);
  840. db_escape_string(gs_szBuffer, "\"");
  841. format(gs_szBuffer, sizeof(gs_szBuffer), "ATTACH DATABASE ':memory:' AS \"%s\"", gs_szBuffer);
  842. return db_exec(db, gs_szBuffer);
  843. }
  844. stock bool:db_detach_memory_db(DB:db, const szName[]) {
  845. strunpack(gs_szBuffer, szName);
  846. db_escape_string(gs_szBuffer, "\"");
  847. format(gs_szBuffer, sizeof(gs_szBuffer), "DETACH DATABASE \"%s\"", gs_szBuffer);
  848. return db_exec(db, gs_szBuffer);
  849. }
  850. stock db_total_changes(DB:db) {
  851. DB::LazyInitialize();
  852. if (!db) {
  853. DB::Error("(db_changes) Invalid database handle given.");
  854. return 0;
  855. }
  856. return db_get_struct_info(db, sqlite3_iNumTotalChanges);
  857. }
  858. stock db_last_insert_rowid(DB:db) {
  859. DB::LazyInitialize();
  860. if (!db) {
  861. DB::Error("(db_last_insert_rowid) Invalid database handle given.");
  862. return 0;
  863. }
  864. return db_get_struct_info(db, sqlite3_iLastRowid);
  865. }
  866. stock db_field_is_null(DBResult:dbrResult, iField) {
  867. if (dbrResult == DB::INVALID_RESULT) {
  868. DB::Notice("(db_field_is_null) Invalid result given.");
  869. return false;
  870. }
  871. new
  872. iAddress = db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative(),
  873. iCols,
  874. iCurrentRow
  875. ;
  876. iAddress += 4;
  877. #emit LREF.S.pri iAddress
  878. #emit STOR.S.pri iCols
  879. if (iField >= iCols)
  880. return true;
  881. iAddress += 8;
  882. #emit LREF.S.pri iAddress
  883. #emit STOR.S.pri iCurrentRow
  884. iAddress -= 4;
  885. #emit LREF.S.pri iAddress
  886. #emit STOR.S.pri iAddress
  887. iAddress -= DB::GetAmxBaseRelative();
  888. iAddress += (iCols + iCols * iCurrentRow + iField) * 4;
  889. #emit LREF.S.pri iAddress
  890. #emit CONST.alt gs_szNull
  891. #emit SUB
  892. #emit STOR.S.pri iAddress
  893. iAddress -= DB::GetAmxBaseRelative();
  894. return !iAddress;
  895. }
  896. stock db_autofree_result(DBResult:dbrResult) {
  897. DB::LazyInitialize();
  898. if (dbrResult == DB::INVALID_RESULT) {
  899. DB::Notice("(db_autofree_result) Invalid result given.");
  900. return;
  901. }
  902. if (gs_iAutoFreeTimer == -1)
  903. gs_iAutoFreeTimer = SetTimer("db_drain_autofree_pool", 0, false);
  904. if (gs_iAutoFreeResultsIndex + 1 >= sizeof(gs_adbrAutoFreeResults)) {
  905. DB::Warning("(db_autofree_result) The autofree pool is full!");
  906. return;
  907. }
  908. gs_adbrAutoFreeResults[gs_iAutoFreeResultsIndex] = dbrResult;
  909. DB::Debug("(db_autofree_result) Will autofree 0x%04x%04x.", _:dbrResult >>> 16, _:dbrResult & 0xFFFF);
  910. gs_iAutoFreeResultsIndex++;
  911. }
  912. stock DBStatement:db_prepare(DB:db, const szQuery[]) {
  913. DB::LazyInitialize();
  914. new
  915. DBStatement:stStatement = DB::INVALID_STATEMENT,
  916. iPos,
  917. i,
  918. iLength
  919. ;
  920. if (!db) {
  921. DB::Error("(db_prepare) Invalid database handle given.");
  922. return DB::INVALID_STATEMENT;
  923. }
  924. // Pretty useless to prepare empty queries.
  925. if (!(iLength = strlen(szQuery))) {
  926. DB::Error("(db_prepare) Empty query.");
  927. return DB::INVALID_STATEMENT;
  928. }
  929. if (iLength char > DB::MAX_STATEMENT_SIZE) {
  930. DB::Error("(db_prepare) The query is too long. Increase DB_MAX_STATEMENT_SIZE.");
  931. return DB::INVALID_STATEMENT;
  932. }
  933. // Find an empty slot in gs_Statements.
  934. for (i = 0; i < sizeof(gs_Statements); i++) {
  935. if (!gs_Statements[DBStatement:i][e_dbDatabase]) {
  936. stStatement = DBStatement:i;
  937. break;
  938. }
  939. }
  940. if (stStatement == DB::INVALID_STATEMENT) {
  941. DB::Error("(db_prepare) Unable to find an empty slot for the statement. Increase DB_MAX_STATEMENTS.");
  942. return DB::INVALID_STATEMENT;
  943. }
  944. gs_Statements[stStatement][e_dbDatabase] = db;
  945. gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
  946. gs_Statements[stStatement][e_iFetchedRows] = 0;
  947. // Make sure no parameters are initialized.
  948. for (i = 0; i < DB::MAX_PARAMS; i++)
  949. gs_Statements[stStatement][e_aiParamTypes][i] = DB::TYPE_NONE;
  950. // Make sure no return fields are initialized.
  951. for (i = 0; i < DB::MAX_FIELDS; i++)
  952. gs_Statements[stStatement][e_aiFieldTypes][i] = DB::TYPE_NONE;
  953. iPos = -1;
  954. i = 0;
  955. // Find all parameters
  956. while (-1 != (iPos = strfind(szQuery, !"?", _, ++iPos))) {
  957. gs_Statements[stStatement][e_aiParamPositions][i] = iPos;
  958. gs_Statements[stStatement][e_aiParamLengths][i] = 1;
  959. if (++i >= DB::MAX_PARAMS) {
  960. DB::Error("(db_prepare) Parameter limit exceeded. Increase DB_MAX_PARAMS.");
  961. return DB::INVALID_STATEMENT;
  962. }
  963. }
  964. gs_Statements[stStatement][e_iParams] = i;
  965. gs_Statements[stStatement][e_szQuery][0] = 0;
  966. if (ispacked(szQuery)) {
  967. #if DB_DEBUG
  968. strunpack(gs_szBuffer, szQuery);
  969. DB::Debug("(db_prepare=%d) Preparing statement with %d params: %s", _:stStatement, i, gs_szBuffer);
  970. #endif
  971. strcat(gs_Statements[stStatement][e_szQuery], szQuery, DB::MAX_STATEMENT_SIZE);
  972. } else {
  973. DB::Debug("(db_prepare=%d) Preparing statement with %d params: %s", _:stStatement, i, szQuery);
  974. strpack(gs_Statements[stStatement][e_szQuery], szQuery, DB::MAX_STATEMENT_SIZE);
  975. }
  976. return stStatement;
  977. }
  978. stock bool:stmt_bind_value(&DBStatement:stStatement, iParam, DBDataType:iType, {Float, _}:...) {
  979. DB::LazyInitialize();
  980. new
  981. iLengthDiff,
  982. iLength,
  983. bool:bIsPacked,
  984. iNumArgs
  985. ;
  986. #emit LOAD.S.pri 8
  987. #emit SHR.C.pri 2
  988. #emit STOR.S.pri iNumArgs
  989. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  990. DB::Warningf("(stmt_bind_value) Invalid statement passed (%d).", _:stStatement);
  991. return false;
  992. }
  993. if (iParam >= gs_Statements[stStatement][e_iParams]) {
  994. DB::Warningf("(stmt_bind_value) Parameter index larger than number of parameters (%d > %d).", iParam, gs_Statements[stStatement][e_iParams]);
  995. return false;
  996. }
  997. // Fill gs_szBuffer with the new contents.
  998. gs_szBuffer[0] = 0;
  999. switch (iType) {
  1000. case DB::TYPE_NULL:
  1001. goto default_case;
  1002. case DB::TYPE_INT: {
  1003. new
  1004. iArgValue = getarg(3)
  1005. ;
  1006. if (iArgValue == cellmin)
  1007. gs_szBuffer = !"-2147483648";
  1008. else
  1009. format(gs_szBuffer, sizeof(gs_szBuffer), "%d", getarg(3));
  1010. }
  1011. case DB::TYPE_UINT: {
  1012. new
  1013. iArgValue = getarg(3)
  1014. ;
  1015. if (!iArgValue) {
  1016. gs_szBuffer = !"0";
  1017. } else {
  1018. new
  1019. j = 11
  1020. ;
  1021. gs_szBuffer = "00000000000";
  1022. while (iArgValue) {
  1023. // gs_szBuffer[--j]
  1024. #emit CONST.alt gs_szBuffer // alt = *gs_szBuffer
  1025. #emit LOAD.S.pri j // pri = j
  1026. #emit DEC.pri // pri -= 1
  1027. #emit STOR.S.pri j // j = pri
  1028. #emit IDXADDR // pri = alt + j * 4
  1029. #emit PUSH.pri // Store for later
  1030. // Now do an unsigned divide on iArgValue then use both the quotient and remainder!
  1031. #emit LOAD.S.pri iArgValue // pri = iArgValue
  1032. #emit CONST.alt 10
  1033. #emit UDIV // pri = iArgValue / 10; alt = iArgValue % 10
  1034. #emit STOR.S.pri iArgValue // iArgValue = pri
  1035. #emit CONST.pri '0'
  1036. #emit ADD // pri = '0' + (iArgValue % 10)
  1037. #emit POP.alt // alt = gs_szBuffer[j]
  1038. #emit STOR.I // gs_szBuffer[j] = pri
  1039. }
  1040. strpack(gs_szBuffer, gs_szBuffer[j]);
  1041. }
  1042. }
  1043. case DB::TYPE_FLOAT:
  1044. format(gs_szBuffer, sizeof(gs_szBuffer), "%f", getarg(3));
  1045. case DB::TYPE_STRING: {
  1046. new iSize = sizeof(gs_szBuffer) - 3;
  1047. //strpack(dest[], const source[], maxlength = sizeof dest)
  1048. #emit PUSH.S iSize
  1049. #emit PUSH.S 24 // arg 3
  1050. #emit PUSH.C gs_szBuffer
  1051. #emit PUSH.C 12
  1052. #emit SYSREQ.C strpack
  1053. #emit STACK 16
  1054. db_escape_string(gs_szBuffer, "'", sizeof(gs_szBuffer) - 1);
  1055. strins(gs_szBuffer, !"'", 0);
  1056. strcat(gs_szBuffer, !"'");
  1057. }
  1058. #if DB::USE_WHIRLPOOL
  1059. case DB::TYPE_WP_HASH: {
  1060. strcat(gs_szBuffer, "x'");
  1061. DB::getstringarg(gs_szBuffer[2], 3, sizeof(gs_szBuffer) - 2);
  1062. DB::WP_Hash(gs_szBuffer[2], sizeof(gs_szBuffer) - 2, gs_szBuffer[2]);
  1063. strcat(gs_szBuffer, "'");
  1064. }
  1065. #endif
  1066. case DB::TYPE_PLAYER_NAME: {
  1067. new
  1068. iPlayer = getarg(3)
  1069. ;
  1070. if (!(0 <= iPlayer < MAX_PLAYERS) || !IsPlayerConnected(iPlayer)) {
  1071. DB::Warningf("(stmt_bind_value) Invalid player ID passed for DB::TYPE_PLAYER_NAME (%d).", iPlayer);
  1072. strcat(gs_szBuffer, !"''");
  1073. } else {
  1074. gs_szBuffer[0] = '\'';
  1075. GetPlayerName(iPlayer, gs_szBuffer[1], sizeof(gs_szBuffer) - 1);
  1076. db_escape_string(gs_szBuffer[1], "'", sizeof(gs_szBuffer) - 1);
  1077. strcat(gs_szBuffer, "'");
  1078. }
  1079. }
  1080. case DB::TYPE_PLAYER_IP: {
  1081. new
  1082. iPlayer = getarg(3)
  1083. ;
  1084. if (!(0 <= iPlayer < MAX_PLAYERS) || !IsPlayerConnected(iPlayer)) {
  1085. DB::Warningf("(stmt_bind_value) Invalid player ID passed for DB::TYPE_PLAYER_IP (%d).", iPlayer);
  1086. strcat(gs_szBuffer, !"''");
  1087. } else {
  1088. gs_szBuffer[0] = '\'';
  1089. GetPlayerIp(iPlayer, gs_szBuffer[1], sizeof(gs_szBuffer) - 1);
  1090. db_escape_string(gs_szBuffer[1], "'", sizeof(gs_szBuffer) - 1);
  1091. strcat(gs_szBuffer, "'");
  1092. }
  1093. }
  1094. // http://www.sqlite.org/lang_keywords.html
  1095. case DB::TYPE_IDENTIFIER: {
  1096. bIsPacked = !!DB::isargpacked(3);
  1097. if (!bIsPacked)
  1098. gs_szBuffer[0] = '"';
  1099. DB::getstringarg(gs_szBuffer[bIsPacked ? 0 : 1], 3, sizeof(gs_szBuffer) - 3);
  1100. db_escape_string(gs_szBuffer[bIsPacked ? 0 : 1], "\"", sizeof(gs_szBuffer) - 1);
  1101. if (bIsPacked)
  1102. strins(gs_szBuffer, "\"", 0);
  1103. strcat(gs_szBuffer, "\"");
  1104. }
  1105. case DB::TYPE_RAW_STRING:
  1106. DB::getstringarg(gs_szBuffer, 3);
  1107. case DB::TYPE_ARRAY: {
  1108. // DB::CompressArray(const aiArray[], iSize = sizeof(aiArray), aiOutput[])
  1109. if (iNumArgs != 5) {
  1110. DB::Error("(stmt_bind_value) Invalid argument count. DB::TYPE_ARRAY requires an additional argument containing the array's length.");
  1111. return false;
  1112. }
  1113. new
  1114. iCompressedSize,
  1115. i
  1116. ;
  1117. // Push the output array
  1118. #emit PUSH.C gs_aiCompressBuffer
  1119. // Push the size
  1120. #emit LREF.S.pri 28 // 12 + 4 cells
  1121. #emit PUSH.pri
  1122. // Push the input array
  1123. #emit PUSH.S 24
  1124. // Push the argument count
  1125. #emit PUSH.C 12
  1126. // Push the return address
  1127. #emit LCTRL 6
  1128. #emit ADD.C 28
  1129. #emit PUSH.pri
  1130. // Call DB::CompressArray
  1131. #emit CONST.pri DB_CompressArray
  1132. #emit SCTRL 6
  1133. // Store the return value
  1134. #emit STOR.S.pri iCompressedSize
  1135. iCompressedSize = (iCompressedSize + 3) / 4;
  1136. gs_szBuffer[0] = 'x';
  1137. gs_szBuffer[1] = '\'';
  1138. if ((iCompressedSize << 3) + 1 < sizeof(gs_szBuffer)) {
  1139. for (i = 0; i < iCompressedSize; i++)
  1140. format(gs_szBuffer[2 + (i << 3)], sizeof(gs_szBuffer) - (2 + (i << 3)), "%01x%07x", gs_aiCompressBuffer[i] >>> 28, gs_aiCompressBuffer[i] & 0x0FFFFFFF);
  1141. } else {
  1142. strcat(gs_szBuffer, "00");
  1143. DB::Errorf("(stmt_bind_value) Unable to compress the array; out of buffer size (has %d, needs %d).", sizeof(gs_szBuffer), (iCompressedSize << 3) + 2);
  1144. return false;
  1145. }
  1146. strcat(gs_szBuffer, "'");
  1147. }
  1148. default: {
  1149. default_case:
  1150. strcat(gs_szBuffer, "NULL");
  1151. }
  1152. }
  1153. iLength = strlen(gs_szBuffer);
  1154. iLengthDiff = iLength - gs_Statements[stStatement][e_aiParamLengths][iParam];
  1155. // Adjust the position of any params after the one being modified.
  1156. for (new i = iParam + 1; i < gs_Statements[stStatement][e_iParams]; i++)
  1157. gs_Statements[stStatement][e_aiParamPositions][i] += iLengthDiff;
  1158. // Delete the old parameter from the query.
  1159. strdel(gs_Statements[stStatement][e_szQuery], gs_Statements[stStatement][e_aiParamPositions][iParam], gs_Statements[stStatement][e_aiParamPositions][iParam] + gs_Statements[stStatement][e_aiParamLengths][iParam]);
  1160. // Make sure we have enough space.
  1161. if ((strlen(gs_Statements[stStatement][e_szQuery]) + iLength) char > DB::MAX_STATEMENT_SIZE) {
  1162. DB::Error("(stmt_bind_value) Buffer overflow. Increase DB_MAX_STATEMENT_SIZE.");
  1163. stmt_close(stStatement);
  1164. return false;
  1165. }
  1166. // Insert the new parameter.
  1167. strins(gs_Statements[stStatement][e_szQuery], gs_szBuffer, gs_Statements[stStatement][e_aiParamPositions][iParam], DB::MAX_STATEMENT_SIZE);
  1168. #if DB_DEBUG
  1169. if (ispacked(gs_szBuffer))
  1170. strunpack(gs_szBuffer, gs_szBuffer);
  1171. DB::Debug("(stmt_bind_value:%d) Inserted new value for parameter %d at %d: %s", _:stStatement, iParam, gs_Statements[stStatement][e_aiParamPositions][iParam], gs_szBuffer);
  1172. #endif
  1173. gs_Statements[stStatement][e_aiParamLengths][iParam] = iLength;
  1174. gs_Statements[stStatement][e_aiParamTypes][iParam] = iType;
  1175. return true;
  1176. }
  1177. stock stmt_bind_result_field(&DBStatement:stStatement, iField, DBDataType:iType, {Float, _}:...) {
  1178. DB::LazyInitialize();
  1179. new
  1180. iAddress,
  1181. iSize,
  1182. iNumArgs
  1183. ;
  1184. #emit LOAD.S.pri 8
  1185. #emit SHR.C.pri 2
  1186. #emit STOR.S.pri iNumArgs
  1187. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1188. DB::Warningf("(stmt_bind_result_field) Invalid statement passed (%d).", _:stStatement);
  1189. return;
  1190. }
  1191. if (iField < 0) {
  1192. DB::Errorf("(stmt_bind_result_field) Negative field index (%d).", iField);
  1193. return;
  1194. }
  1195. switch (iType) {
  1196. case DB::TYPE_STRING,
  1197. DB::TYPE_RAW_STRING,
  1198. DB::TYPE_IDENTIFIER,
  1199. DB::TYPE_ARRAY: {
  1200. if (iNumArgs != 5) {
  1201. DB::Error("(stmt_bind_result_field) Invalid number of arguments passed. Strings and arrays require an additional argument containing the string size.");
  1202. return;
  1203. }
  1204. iSize = getarg(4);
  1205. }
  1206. case DB::TYPE_NONE: {
  1207. gs_Statements[stStatement][e_aiFieldTypes][iField] = DB::TYPE_NONE;
  1208. return;
  1209. }
  1210. default: {
  1211. if (iNumArgs != 4) {
  1212. DB::Error("(stmt_bind_result_field) Invalid number of arguments passed.");
  1213. return;
  1214. }
  1215. iSize = 1;
  1216. }
  1217. }
  1218. if (iField >= DB::MAX_FIELDS) {
  1219. DB::Warningf("(stmt_bind_result_field) Field index larger than max number of fields (%d > %d). Increase DB_MAX_FIELDS.", iField, DB::MAX_FIELDS);
  1220. return;
  1221. }
  1222. // Without this, STOR.S.pri doesn't seem to do what it should.
  1223. iAddress = 0;
  1224. #emit LOAD.S.pri 24
  1225. #emit STOR.S.pri iAddress
  1226. gs_Statements[stStatement][e_aiFieldTypes][iField] = iType;
  1227. gs_Statements[stStatement][e_aiFieldAddresses][iField] = iAddress;
  1228. gs_Statements[stStatement][e_aiFieldSizes][iField] = iSize;
  1229. DB::Debug("(stmt_bind_result_field:%d) Bound result field %d (type %d) to variable 0x%04x%04x.", _:stStatement, iField, _:iType, iAddress >>> 16, iAddress & 0xFFFF);
  1230. }
  1231. stock bool:stmt_skip_row(&DBStatement:stStatement) {
  1232. DB::LazyInitialize();
  1233. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1234. DB::Errorf("(stmt_skip_row) Invalid statement passed (%d).", _:stStatement);
  1235. return false;
  1236. }
  1237. if (gs_Statements[stStatement][e_dbrResult] == DB::INVALID_RESULT) {
  1238. if (!gs_Statements[stStatement][e_iFetchedRows])
  1239. DB::Warning("(stmt_skip_row) Statement has no result.");
  1240. return false;
  1241. }
  1242. gs_Statements[stStatement][e_iFetchedRows]++;
  1243. if (!db_next_row(gs_Statements[stStatement][e_dbrResult])) {
  1244. db_free_result(gs_Statements[stStatement][e_dbrResult]);
  1245. gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
  1246. DB::Debug("(stmt_skip_row:%d) Skipped row and freed result.", _:stStatement);
  1247. } else {
  1248. DB::Debug("(stmt_skip_row:%d) Skipped row.", _:stStatement);
  1249. }
  1250. return true;
  1251. }
  1252. stock bool:stmt_fetch_row(&DBStatement:stStatement) {
  1253. DB::LazyInitialize();
  1254. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1255. DB::Errorf("(stmt_fetch_row) Invalid statement passed (%d).", _:stStatement);
  1256. return false;
  1257. }
  1258. if (gs_Statements[stStatement][e_dbrResult] == DB::INVALID_RESULT) {
  1259. if (!gs_Statements[stStatement][e_iFetchedRows])
  1260. DB::Warning("(stmt_fetch_row) Statement has no result.");
  1261. return false;
  1262. }
  1263. if (!stmt_rows_left(stStatement)) {
  1264. DB::Debug("(stmt_fetch_row) No rows left.");
  1265. return false;
  1266. }
  1267. if (!db_num_rows(gs_Statements[stStatement][e_dbrResult])) {
  1268. DB::Debug("(stmt_fetch_row) Freed previous result.");
  1269. db_free_result(gs_Statements[stStatement][e_dbrResult]);
  1270. gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
  1271. return false;
  1272. }
  1273. new
  1274. iFields = db_num_fields(gs_Statements[stStatement][e_dbrResult]),
  1275. iAddress,
  1276. xValue,
  1277. iCount
  1278. ;
  1279. if (iFields > DB::MAX_FIELDS) {
  1280. DB::Warning("(stmt_bind_result_field) There are more fields returned than DB_MAX_FIELDS.");
  1281. iFields = DB::MAX_FIELDS;
  1282. }
  1283. gs_Statements[stStatement][e_iFetchedRows]++;
  1284. for (new iField = 0; iField < iFields; iField++) {
  1285. if (gs_Statements[stStatement][e_aiFieldTypes][iField] == DB::TYPE_NONE)
  1286. continue;
  1287. iCount++;
  1288. switch (gs_Statements[stStatement][e_aiFieldTypes][iField]) {
  1289. case DB::TYPE_NONE,
  1290. DB::TYPE_NULL:
  1291. continue;
  1292. case DB::TYPE_INT,
  1293. DB::TYPE_UINT,
  1294. DB::TYPE_FLOAT: {
  1295. db_get_field(gs_Statements[stStatement][e_dbrResult], iField, gs_szBuffer, sizeof(gs_szBuffer) - 1);
  1296. iAddress = gs_Statements[stStatement][e_aiFieldAddresses][iField];
  1297. xValue = (gs_Statements[stStatement][e_aiFieldTypes][iField] != DB::TYPE_FLOAT) ? strval(gs_szBuffer) : _:floatstr(gs_szBuffer);
  1298. #emit LOAD.S.pri xValue
  1299. #emit SREF.S.pri iAddress
  1300. }
  1301. // Assumes the field is a string containing a player name.
  1302. // Gives the ID of a connected play with that name, otherwise INVALID_PLAYER_ID.
  1303. case DB::TYPE_PLAYER_NAME: {
  1304. static
  1305. s_szName[MAX_PLAYER_NAME]
  1306. ;
  1307. xValue = INVALID_PLAYER_ID;
  1308. for (new i = 0, l = GetMaxPlayers(); i < l; i++) {
  1309. if (!IsPlayerConnected(i))
  1310. continue;
  1311. GetPlayerName(i, s_szName, sizeof(s_szName));
  1312. db_get_field(gs_Statements[stStatement][e_dbrResult], iField, gs_szBuffer, sizeof(gs_szBuffer) - 1);
  1313. if (!strcmp(gs_szBuffer, s_szName, true)) {
  1314. xValue = i;
  1315. break;
  1316. }
  1317. }
  1318. iAddress = gs_Statements[stStatement][e_aiFieldAddresses][iField];
  1319. #emit LOAD.S.pri xValue
  1320. #emit SREF.S.pri iAddress
  1321. }
  1322. case DB::TYPE_STRING,
  1323. DB::TYPE_RAW_STRING,
  1324. DB::TYPE_IDENTIFIER: {
  1325. new
  1326. DBResult:dbrResult,
  1327. iSize
  1328. ;
  1329. static const
  1330. sc_szFormatString[] = "%s"
  1331. ;
  1332. iAddress = gs_Statements[stStatement][e_aiFieldAddresses][iField];
  1333. dbrResult = gs_Statements[stStatement][e_dbrResult];
  1334. iSize = gs_Statements[stStatement][e_aiFieldSizes][iField];
  1335. #emit PUSH.S iSize
  1336. #emit PUSH.S iAddress
  1337. #emit PUSH.S iField
  1338. #emit PUSH.S dbrResult
  1339. #emit PUSH.C 16
  1340. #emit SYSREQ.C db_get_field
  1341. #emit STACK 20
  1342. // Fix a bug with UTF-8 characters
  1343. // For example, 'ö' would become 0xFFFFFFC3 instead of 0xC3
  1344. #emit PUSH.S iAddress
  1345. #emit PUSH.C sc_szFormatString
  1346. #emit PUSH.S iSize
  1347. #emit PUSH.S iAddress
  1348. #emit PUSH.C 16
  1349. #emit SYSREQ.C format
  1350. #emit STACK 20
  1351. }
  1352. case DB::TYPE_ARRAY: {
  1353. // DecompressArray(const aiCompressedArray[], aiOutput[], iOutputSize = sizeof(aiOutput))
  1354. db_get_field(gs_Statements[stStatement][e_dbrResult], iField, gs_szBuffer, sizeof(gs_szBuffer) - 1);
  1355. format(gs_szBuffer, sizeof(gs_szBuffer), "%s", gs_szBuffer);
  1356. strpack(gs_szBuffer, gs_szBuffer);
  1357. new
  1358. iOutputSize = gs_Statements[stStatement][e_aiFieldSizes][iField],
  1359. iDecompressedCells
  1360. ;
  1361. iAddress = gs_Statements[stStatement][e_aiFieldAddresses][iField];
  1362. // Push the output array size
  1363. #emit PUSH.S iOutputSize
  1364. // Push the output array
  1365. #emit PUSH.S iAddress
  1366. // Push the input array
  1367. #emit PUSH.C gs_szBuffer
  1368. // Push the argument count
  1369. #emit PUSH.C 12
  1370. // Push the return address
  1371. #emit LCTRL 6
  1372. #emit ADD.C 28
  1373. #emit PUSH.pri
  1374. // Call DB::DecompressArray
  1375. #emit CONST.pri DB_DecompressArray
  1376. #emit SCTRL 6
  1377. // Store the return address
  1378. #emit STOR.S.pri iDecompressedCells
  1379. // If there are more cells in the array, fill them with 0
  1380. if (iOutputSize > iDecompressedCells) {
  1381. DB::Noticef("(stmt_fetch_row:%d) The array fetched from the DB is smaller than the destination array (%d > %d); the remaining slots with will be filled with 0.", _:stStatement, iOutputSize, iDecompressedCells);
  1382. iAddress += iDecompressedCells * 4-4;
  1383. iOutputSize = iOutputSize - iDecompressedCells;
  1384. // DB::memset(aArray[], iValue, iSize = sizeof(aArray))
  1385. #emit PUSH.S iOutputSize
  1386. #emit PUSH.C 0
  1387. #emit PUSH.S iAddress
  1388. #emit PUSH.C 12
  1389. #emit LCTRL 6
  1390. #emit ADD.C 28
  1391. #emit PUSH.pri
  1392. #emit CONST.pri DB_memset
  1393. #emit SCTRL 6
  1394. }
  1395. }
  1396. }
  1397. }
  1398. if (!db_next_row(gs_Statements[stStatement][e_dbrResult])) {
  1399. db_free_result(gs_Statements[stStatement][e_dbrResult]);
  1400. gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
  1401. DB::Debug("(stmt_fetch_row:%d) Fetched %d fields and freed the result.", _:stStatement, iCount);
  1402. } else {
  1403. DB::Debug("(stmt_fetch_row:%d) Fetched %d fields.", _:stStatement, iCount);
  1404. }
  1405. return true;
  1406. }
  1407. stock stmt_rows_left(&DBStatement:stStatement) {
  1408. DB::LazyInitialize();
  1409. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1410. DB::Errorf("(stmt_rows_left) Invalid statement passed (%d).", _:stStatement);
  1411. return 0;
  1412. }
  1413. if (gs_Statements[stStatement][e_dbrResult] == DB::INVALID_RESULT) {
  1414. if (!gs_Statements[stStatement][e_iFetchedRows])
  1415. DB::Warning("(stmt_rows_left) Statement has no result.");
  1416. return 0;
  1417. }
  1418. return max(0, db_num_rows(gs_Statements[stStatement][e_dbrResult]) - gs_Statements[stStatement][e_iFetchedRows]);
  1419. }
  1420. stock bool:stmt_execute(&DBStatement:stStatement, bool:bStoreResult = true, bool:bAutoFreeResult = true) {
  1421. DB::LazyInitialize();
  1422. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1423. DB::Errorf("(stmt_execute) Invalid statement passed (%d).", _:stStatement);
  1424. return false;
  1425. }
  1426. if (!gs_Statements[stStatement][e_dbDatabase]) {
  1427. DB::Errorf("(stmt_execute) Uninitialized statement passed (%d).", _:stStatement);
  1428. return false;
  1429. }
  1430. // Make sure all parameters have been set.
  1431. for (new i = 0; i < gs_Statements[stStatement][e_iParams]; i++) {
  1432. if (gs_Statements[stStatement][e_aiParamTypes][i] == DB::TYPE_NONE) {
  1433. DB::Errorf("(stmt_execute) Uninitialized parameter in statement (%d).", i);
  1434. return false;
  1435. }
  1436. }
  1437. // If old results are left, free them.
  1438. if (gs_Statements[stStatement][e_dbrResult] != DB::INVALID_RESULT) {
  1439. db_free_result(gs_Statements[stStatement][e_dbrResult]);
  1440. gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
  1441. }
  1442. DB::Debug("(stmt_execute:%d) Executing statement.", _:stStatement);
  1443. new
  1444. DBResult:dbrResult = db_query(gs_Statements[stStatement][e_dbDatabase], gs_Statements[stStatement][e_szQuery], false)
  1445. ;
  1446. gs_Statements[stStatement][e_iFetchedRows] = 0;
  1447. gs_Statements[stStatement][e_bAutoFreeResult] = bAutoFreeResult;
  1448. if (dbrResult == DB::INVALID_RESULT)
  1449. return false;
  1450. if (!bStoreResult)
  1451. db_free_result(dbrResult);
  1452. else {
  1453. gs_Statements[stStatement][e_dbrResult] = dbrResult;
  1454. if (bAutoFreeResult && gs_iFreeStatementResultsTimer == -1)
  1455. gs_iFreeStatementResultsTimer = SetTimer("db_free_stmt_results", 1, false);
  1456. }
  1457. return true;
  1458. }
  1459. stock stmt_free_result(&DBStatement:stStatement) {
  1460. DB::LazyInitialize();
  1461. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1462. DB::Noticef("(stmt_free_result) Invalid statement passed (%d).", _:stStatement);
  1463. return;
  1464. }
  1465. gs_Statements[stStatement][e_iFetchedRows] = 0;
  1466. if (gs_Statements[stStatement][e_dbrResult] != DB::INVALID_RESULT) {
  1467. db_free_result(gs_Statements[stStatement][e_dbrResult]);
  1468. gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
  1469. DB::Debug("(stmt_free_result:%d) Freed result.", _:stStatement);
  1470. } else {
  1471. DB::Debug("(stmt_free_result:%d) Nothing to free.", _:stStatement);
  1472. }
  1473. }
  1474. stock stmt_close(&DBStatement:stStatement) {
  1475. DB::LazyInitialize();
  1476. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1477. DB::Noticef("(stmt_close) Invalid statement passed (%d).", _:stStatement);
  1478. return;
  1479. }
  1480. if (gs_Statements[stStatement][e_dbrResult] != DB::INVALID_RESULT)
  1481. db_free_result(gs_Statements[stStatement][e_dbrResult]);
  1482. gs_Statements[stStatement][e_dbDatabase] = DB:0;
  1483. DB::Debug("(stmt_close:%d) Closed statement.", _:stStatement);
  1484. stStatement = DB::INVALID_STATEMENT;
  1485. }
  1486. stock stmt_autoclose(&DBStatement:stStatement) {
  1487. DB::LazyInitialize();
  1488. if (stStatement == DB::INVALID_STATEMENT || !(0 <= _:stStatement < sizeof(gs_Statements))) {
  1489. DB::Noticef("(stmt_autoclose) Invalid statement passed (%d).", _:stStatement);
  1490. return;
  1491. }
  1492. if (gs_iAutoFreeTimer == -1)
  1493. gs_iAutoFreeTimer = SetTimer("db_drain_autofree_pool", 0, false);
  1494. if (gs_iAutoCloseStatementsIndex + 1 >= sizeof(gs_astAutoCloseStatements)) {
  1495. DB::Warning("(stmt_autoclose) The autoclose pool is full!");
  1496. return;
  1497. }
  1498. gs_astAutoCloseStatements[gs_iAutoCloseStatementsIndex] = stStatement;
  1499. gs_iAutoCloseStatementsIndex++;
  1500. DB::Debug("(stmt_autoclose:%d) Will autoclose statement.", _:stStatement);
  1501. }
  1502. stock DBResult:db_query_hook(iTagOf3 = tagof(_bAutoRelease), DB:db, const szQuery[], {bool, DBDataType}:_bAutoRelease = true, {DBDataType, QQPA}:...) {
  1503. new
  1504. iIndex,
  1505. iNumArgs,
  1506. iStaticArgs = 4,
  1507. bool:bAutoRelease = true
  1508. ;
  1509. #emit LOAD.S.pri 8
  1510. #emit SHR.C.pri 2
  1511. #emit STOR.S.pri iNumArgs
  1512. DB::LazyInitialize();
  1513. if (iTagOf3 == tagof(DBDataType:)) {
  1514. iStaticArgs = 3;
  1515. } else {
  1516. bAutoRelease = _bAutoRelease;
  1517. }
  1518. if (db_is_persistent(db)) {
  1519. if (!db_is_valid_persistent(db)) {
  1520. DB::Errorf("(db_query) Invalid persistent database given (%04x%04x).", _:db >>> 16, _:db & 0xFFFF);
  1521. return DB::INVALID_RESULT;
  1522. }
  1523. iIndex = _:db & 0x7FFFFFFF;
  1524. if (!gs_PersistentDatabases[iIndex][e_dbDatabase]) {
  1525. if (!(gs_PersistentDatabases[iIndex][e_dbDatabase] = db_open(gs_PersistentDatabases[iIndex][e_szName]))) {
  1526. DB::Errorf("(db_query) Failed to lazily open the database.");
  1527. return DB::INVALID_RESULT;
  1528. }
  1529. if (gs_iClosePersistentTimer == -1)
  1530. gs_iClosePersistentTimer = SetTimer("db_close_persistent", 0, false);
  1531. }
  1532. db = gs_PersistentDatabases[iIndex][e_dbDatabase];
  1533. }
  1534. #if DB_DEBUG
  1535. if (ispacked(szQuery)) {
  1536. strunpack(gs_szBuffer, szQuery);
  1537. DB::Debug("(db_query) Running query: %s", gs_szBuffer);
  1538. } else {
  1539. DB::Debug("(db_query) Running query: %s", szQuery);
  1540. }
  1541. #endif
  1542. new
  1543. DBResult:dbrResult
  1544. ;
  1545. if (iNumArgs > iStaticArgs) {
  1546. if ((iNumArgs - iStaticArgs) & 0b1) {
  1547. DB::Error("(db_query) Invalid argument count. Did you forget to use the correct prefix on the arguments (e.g. STRING:somestring)?");
  1548. return DB::INVALID_RESULT;
  1549. }
  1550. new DBStatement:stmt = db_prepare(db, szQuery);
  1551. for (new i = iStaticArgs + 1; i < iNumArgs; i += 2) {
  1552. // Load the address of argument <i>
  1553. #emit LCTRL 5
  1554. #emit LOAD.S.alt i
  1555. #emit SHL.C.alt 2
  1556. #emit ADD
  1557. #emit ADD.C 12
  1558. #emit MOVE.alt
  1559. #emit LOAD.I
  1560. #emit PUSH.pri
  1561. #emit PUSH.alt
  1562. if (i == 4) {
  1563. // Load the address of argument <i - 1>
  1564. #emit POP.pri
  1565. #emit ADD.C 0xFFFFFFFC
  1566. #emit LOAD.I
  1567. #emit PUSH.pri
  1568. } else {
  1569. // Load the address of argument <i - 1>
  1570. #emit POP.pri
  1571. #emit ADD.C 0xFFFFFFFC
  1572. #emit LOAD.I
  1573. #emit LOAD.I
  1574. #emit PUSH.pri
  1575. }
  1576. // Push the param index: (i - iStaticArgs) / 2
  1577. #emit LOAD.S.pri i
  1578. #emit LOAD.S.alt iStaticArgs
  1579. #emit SUB
  1580. #emit SHR.C.pri 1
  1581. #emit PUSH.pri
  1582. #emit PUSH.ADR stmt
  1583. // Push the argument count
  1584. #emit PUSH.C 16
  1585. // Push the return address
  1586. #emit LCTRL 6
  1587. #emit ADD.C 28
  1588. #emit PUSH.pri
  1589. // Call stmt_bind_value
  1590. #emit CONST.pri stmt_bind_value
  1591. #emit SCTRL 6
  1592. }
  1593. dbrResult = db_query@(db, gs_Statements[stmt][e_szQuery]);
  1594. stmt_close(stmt);
  1595. } else {
  1596. dbrResult = db_query@(db, szQuery);
  1597. }
  1598. if (dbrResult) {
  1599. if (bAutoRelease)
  1600. db_autofree_result(dbrResult);
  1601. new
  1602. iResultAddress = db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative(),
  1603. iAddress,
  1604. iRows,
  1605. iCols,
  1606. iDataAddress,
  1607. iOffset
  1608. ;
  1609. iAddress = iResultAddress;
  1610. #emit LREF.S.pri iAddress
  1611. #emit STOR.S.pri iRows
  1612. iAddress += 4;
  1613. #emit LREF.S.pri iAddress
  1614. #emit STOR.S.pri iCols
  1615. iAddress += 4;
  1616. #emit LREF.S.pri iAddress
  1617. #emit STOR.S.pri iDataAddress
  1618. iDataAddress -= DB::GetAmxBaseRelative();
  1619. iOffset = (iCols + iRows * iCols) * 4 - 4;
  1620. while (iOffset >= 0) {
  1621. iAddress = iDataAddress + iOffset;
  1622. #emit LREF.S.pri iAddress
  1623. #emit STOR.S.pri iAddress
  1624. if (!iAddress) {
  1625. new
  1626. iAmxBaseRelative = DB::GetAmxBaseRelative()
  1627. ;
  1628. iAddress = iDataAddress + iOffset;
  1629. #emit CONST.pri gs_szNull
  1630. #emit LOAD.S.alt iAmxBaseRelative
  1631. #emit ADD
  1632. #emit SREF.S.pri iAddress
  1633. }
  1634. iOffset -= 4;
  1635. }
  1636. }
  1637. return dbrResult;
  1638. }
  1639. stock db_get_field_hook(DBResult:dbresult, field, result[], maxlength = sizeof(result)) {
  1640. new retval = db_get_field(dbresult, field, result, maxlength);
  1641. format(result, maxlength, "%s", result);
  1642. return retval;
  1643. }
  1644. stock db_get_field_assoc_hook(DBResult:dbresult, const field[], result[], maxlength = sizeof(result)) {
  1645. new retval = db_get_field_assoc(dbresult, field, result, maxlength);
  1646. format(result, maxlength, "%s", result);
  1647. return retval;
  1648. }
  1649. stock bool:db_dump_table(DB:db, const szTable[], const szFilename[]) {
  1650. static
  1651. s_szColumnName[256]
  1652. ;
  1653. new
  1654. DBResult:dbrResult,
  1655. File:fp
  1656. ;
  1657. if (strfind(szTable, "\"") != -1 || strfind(szTable, "'") != -1) {
  1658. DB::Error("(db_dump_table) Invalid table name given.");
  1659. return false;
  1660. }
  1661. if (!(fp = fopen(szFilename, io_write))) {
  1662. DB::Error("(db_dump_table) Failed to open the file.");
  1663. return false;
  1664. }
  1665. format(gs_szBuffer, sizeof(gs_szBuffer), "SELECT sql FROM sqlite_master WHERE tbl_name = '%s'", szTable);
  1666. dbrResult = db_query(db, gs_szBuffer);
  1667. if (!dbrResult) {
  1668. DB::Error("(db_dump_table) Failed to get the table sql.");
  1669. return false;
  1670. }
  1671. db_get_field(dbrResult, 0, gs_szBuffer, sizeof(gs_szBuffer) - 1);
  1672. if (strlen(gs_szBuffer) >= sizeof(gs_szBuffer) - 2) {
  1673. DB::Error("(db_dump_table) Buffer overflow.");
  1674. fwrite(fp, "\nBUFFER OVERFLOW");
  1675. fclose(fp);
  1676. db_free_result(dbrResult);
  1677. return false;
  1678. }
  1679. fwrite(fp, gs_szBuffer);
  1680. fwrite(fp, ";\n\n\n");
  1681. db_free_result(dbrResult);
  1682. format(gs_szBuffer, sizeof(gs_szBuffer), "PRAGMA table_info(%s)", szTable);
  1683. dbrResult = db_query(db, gs_szBuffer, false);
  1684. if (!dbrResult) {
  1685. DB::Error("(db_dump_table) Failed to get table info.");
  1686. return false;
  1687. }
  1688. gs_szBuffer = "SELECT 'INSERT INTO ";
  1689. strcat(gs_szBuffer, szTable);
  1690. strcat(gs_szBuffer, " VALUES('");
  1691. if (db_num_rows(dbrResult)) do {
  1692. db_get_field(dbrResult, 1, s_szColumnName, sizeof(s_szColumnName) - 1);
  1693. if (db_get_row_index(dbrResult) > 0)
  1694. strcat(gs_szBuffer, " || ', '");
  1695. strcat(gs_szBuffer, " || quote(");
  1696. strcat(gs_szBuffer, s_szColumnName);
  1697. strcat(gs_szBuffer, ")");
  1698. } while (db_next_row(dbrResult));
  1699. strcat(gs_szBuffer, " || ');' FROM ");
  1700. strcat(gs_szBuffer, szTable);
  1701. db_free_result(dbrResult);
  1702. dbrResult = db_query(db, gs_szBuffer);
  1703. fwrite(fp, "BEGIN;\n\n");
  1704. if (db_num_rows(dbrResult)) do {
  1705. db_get_field(dbrResult, 0, gs_szBuffer, sizeof(gs_szBuffer) - 1);
  1706. if (strlen(gs_szBuffer) >= sizeof(gs_szBuffer) - 2) {
  1707. DB::Error("(db_dump_table) Buffer overflow.");
  1708. fwrite(fp, "\nBUFFER OVERFLOW");
  1709. fclose(fp);
  1710. db_free_result(dbrResult);
  1711. return false;
  1712. }
  1713. fwrite(fp, gs_szBuffer);
  1714. fwrite(fp, "\n");
  1715. } while (db_next_row(dbrResult));
  1716. fwrite(fp, "\nCOMMIT;\n");
  1717. db_free_result(dbrResult);
  1718. fclose(fp);
  1719. return true;
  1720. }
  1721. stock DBResult:db_print_result(DBResult:dbrResult, iMaxFieldLength = 40) {
  1722. DB::LazyInitialize();
  1723. const
  1724. MAX_ROWS = 100,
  1725. MAX_FIELDS = 20,
  1726. MAX_FIELD_LENGTH = 88
  1727. ;
  1728. static
  1729. s_aaszFields[MAX_ROWS + 1][MAX_FIELDS][MAX_FIELD_LENGTH char],
  1730. s_aiFieldMaxLength[MAX_FIELDS]
  1731. ;
  1732. static const
  1733. szcSpacePadding[MAX_FIELD_LENGTH] = {' ', ...},
  1734. szcDashPadding[MAX_FIELD_LENGTH] = {'-', ...}
  1735. ;
  1736. if (iMaxFieldLength == -1)
  1737. iMaxFieldLength = MAX_FIELD_LENGTH;
  1738. print(!" ");
  1739. print(!"Query result:");
  1740. if (!dbrResult)
  1741. print(!"\t- Invalid result.");
  1742. else if (!db_num_rows(dbrResult))
  1743. print(!"\t- No rows.");
  1744. else {
  1745. new
  1746. iRow = 0,
  1747. iRows,
  1748. iFields = db_num_fields(dbrResult),
  1749. iField,
  1750. iLength,
  1751. bool:bHasMoreLines,
  1752. iPos,
  1753. iNextPos,
  1754. iRowIndex = db_get_row_index(dbrResult)
  1755. ;
  1756. db_set_row_index(dbrResult, 0);
  1757. if (iMaxFieldLength > MAX_FIELD_LENGTH) {
  1758. printf("\t- The longest possible field length is %d. Change MAX_FIELD_LENGTH for larger values.", MAX_FIELD_LENGTH);
  1759. iMaxFieldLength = MAX_FIELD_LENGTH;
  1760. }
  1761. if (iFields > MAX_FIELDS) {
  1762. printf("\t- There are %d, but only %d of them will be visible.", iFields, MAX_FIELDS);
  1763. print(!"\t- Increase MAX_FIELDS if you want to see all fields.");
  1764. iFields = MAX_FIELDS;
  1765. }
  1766. for (iField = 0; iField < iFields; iField++) {
  1767. db_field_name(dbrResult, iField, gs_szBuffer, iMaxFieldLength - 1);
  1768. iPos = 0;
  1769. while (-1 != (iPos = strfind(gs_szBuffer, "\r", _, iPos)))
  1770. gs_szBuffer[iPos] = ' ';
  1771. iPos = 0;
  1772. while (-1 != (iPos = strfind(gs_szBuffer, "\t", _, iPos))) {
  1773. gs_szBuffer[iPos] = ' ';
  1774. strins(gs_szBuffer, " ", iPos, iMaxFieldLength);
  1775. iPos += 4;
  1776. }
  1777. iPos = 0;
  1778. do {
  1779. iNextPos = strfind(gs_szBuffer, "\n", _, iPos) + 1;
  1780. if (!iNextPos)
  1781. iLength = strlen(gs_szBuffer[iPos]);
  1782. else
  1783. iLength = iNextPos - iPos - 1;
  1784. s_aiFieldMaxLength[iField] = min(iMaxFieldLength, max(iLength, s_aiFieldMaxLength[iField]));
  1785. } while ((iPos = iNextPos));
  1786. strpack(s_aaszFields[0][iField], gs_szBuffer, iMaxFieldLength char);
  1787. }
  1788. do {
  1789. for (iField = 0; iField < iFields; iField++) {
  1790. if (db_field_is_null(dbrResult, iField))
  1791. gs_szBuffer = "NULL";
  1792. else
  1793. db_get_field(dbrResult, iField, gs_szBuffer, iMaxFieldLength - 1);
  1794. iPos = 0;
  1795. while (-1 != (iPos = strfind(gs_szBuffer, "\r", _, iPos)))
  1796. gs_szBuffer[iPos] = ' ';
  1797. iPos = 0;
  1798. while (-1 != (iPos = strfind(gs_szBuffer, "\t", _, iPos))) {
  1799. gs_szBuffer[iPos] = ' ';
  1800. strins(gs_szBuffer, " ", iPos, iMaxFieldLength);
  1801. iPos += 4;
  1802. }
  1803. iPos = 0;
  1804. do {
  1805. iNextPos = strfind(gs_szBuffer, "\n", _, iPos) + 1;
  1806. if (!iNextPos)
  1807. iLength = strlen(gs_szBuffer[iPos]);
  1808. else
  1809. iLength = iNextPos - iPos - 1;
  1810. s_aiFieldMaxLength[iField] = min(iMaxFieldLength, max(iLength, s_aiFieldMaxLength[iField]));
  1811. } while ((iPos = iNextPos));
  1812. strpack(s_aaszFields[iRow + 1][iField], gs_szBuffer, iMaxFieldLength char);
  1813. }
  1814. if (++iRow >= MAX_ROWS) {
  1815. iRows = iRow;
  1816. while (db_next_row(dbrResult))
  1817. iRows++;
  1818. printf("\t- Only the first %d rows are displayed; there are %d remaining.", MAX_ROWS, iRows);
  1819. break;
  1820. }
  1821. } while (db_next_row(dbrResult));
  1822. print(!" ");
  1823. for (iRows = iRow, iRow = 0; iRow <= iRows; iRow++) {
  1824. do {
  1825. bHasMoreLines = false;
  1826. gs_szBuffer[0] = 0;
  1827. for (iField = 0; iField < iFields; iField++) {
  1828. if (iField)
  1829. strcat(gs_szBuffer, " | ");
  1830. iLength = strlen(gs_szBuffer);
  1831. if (-1 != (iPos = strfind(s_aaszFields[iRow][iField], "\n"))) {
  1832. strunpack(gs_szBuffer[iLength], s_aaszFields[iRow][iField], strlen(gs_szBuffer[iLength]) + iPos + 1);
  1833. strdel(s_aaszFields[iRow][iField], 0, iPos + 1);
  1834. bHasMoreLines = true;
  1835. } else {
  1836. if (s_aaszFields[iRow][iField]{0}) {
  1837. strunpack(gs_szBuffer[iLength], s_aaszFields[iRow][iField], sizeof(gs_szBuffer) - iLength);
  1838. s_aaszFields[iRow][iField]{0} = 0;
  1839. }
  1840. }
  1841. iLength = strlen(gs_szBuffer[iLength]);
  1842. strcat(gs_szBuffer, szcSpacePadding, strlen(gs_szBuffer) + (s_aiFieldMaxLength[iField] - iLength + 1));
  1843. }
  1844. if (bHasMoreLines)
  1845. printf("\t| %s |", gs_szBuffer);
  1846. } while (bHasMoreLines);
  1847. if (iRow == 0) {
  1848. printf("\t/ %s \\", gs_szBuffer);
  1849. } else {
  1850. printf("\t| %s |", gs_szBuffer);
  1851. }
  1852. if (iRow == iRows) {
  1853. gs_szBuffer[0] = 0;
  1854. for (iField = 0; iField < iFields; iField++) {
  1855. if (iField)
  1856. strcat(gs_szBuffer, "---");
  1857. strcat(gs_szBuffer, szcDashPadding, strlen(gs_szBuffer) + s_aiFieldMaxLength[iField] + 1);
  1858. }
  1859. printf("\t\\-%s-/", gs_szBuffer);
  1860. } else {
  1861. gs_szBuffer[0] = 0;
  1862. for (iField = 0; iField < iFields; iField++) {
  1863. if (iField)
  1864. strcat(gs_szBuffer, "-|-");
  1865. strcat(gs_szBuffer, szcDashPadding, strlen(gs_szBuffer) + s_aiFieldMaxLength[iField] + 1);
  1866. }
  1867. printf("\t|-%s-|", gs_szBuffer);
  1868. }
  1869. }
  1870. db_set_row_index(dbrResult, iRowIndex);
  1871. }
  1872. print(!" ");
  1873. return dbrResult;
  1874. }
  1875. stock db_print_query(DB:db, const szQuery[], iMaxFieldLength = 40) {
  1876. new
  1877. DBResult:dbrResult = db_query(db, szQuery, false)
  1878. ;
  1879. db_print_result(dbrResult, iMaxFieldLength);
  1880. db_free_result(dbrResult);
  1881. }
  1882. forward db_drain_autofree_pool();
  1883. public db_drain_autofree_pool() {
  1884. DB::LazyInitialize();
  1885. gs_iAutoFreeTimer = -1;
  1886. for (new i = gs_iAutoFreeResultsIndex; i--; ) {
  1887. if (gs_adbrAutoFreeResults[i]) {
  1888. new DBResult:result = gs_adbrAutoFreeResults[i];
  1889. gs_adbrAutoFreeResults[i] = DB::INVALID_RESULT;
  1890. DB::Debug("(db_drain_autofree_pool) Autofreeing 0x%04x%04x", _:result >>> 16, _:result & 0xFFFF);
  1891. db_free_result_hook(result);
  1892. }
  1893. }
  1894. gs_iAutoFreeResultsIndex = 0;
  1895. for (new i = gs_iAutoCloseStatementsIndex; i--; ) {
  1896. if (gs_astAutoCloseStatements[i]) {
  1897. DB::Debug("(db_drain_autofree_pool) Autoclosing statement %d.", _:gs_astAutoCloseStatements[i]);
  1898. stmt_close(gs_astAutoCloseStatements[i]);
  1899. }
  1900. }
  1901. gs_iAutoCloseStatementsIndex = 0;
  1902. }
  1903. forward db_free_stmt_results();
  1904. public db_free_stmt_results() {
  1905. gs_iFreeStatementResultsTimer = -1;
  1906. for (new DBStatement:i = DBStatement:0; _:i < sizeof(gs_Statements); i++) {
  1907. if (gs_Statements[i][e_dbDatabase]
  1908. && gs_Statements[i][e_bAutoFreeResult]
  1909. && gs_Statements[i][e_dbrResult] != DB::INVALID_RESULT) {
  1910. new DBResult:result = gs_Statements[i][e_dbrResult];
  1911. gs_Statements[i][e_dbrResult] = DB::INVALID_RESULT;
  1912. DB::Debug("(db_free_stmt_results) Freeing 0x%04x%04x for %d.", _:result >>> 16, _:result & 0xFFFF, _:i);
  1913. db_free_result_hook(result);
  1914. }
  1915. }
  1916. }
  1917. forward db_close_persistent();
  1918. public db_close_persistent() {
  1919. gs_iClosePersistentTimer = -1;
  1920. for (new i = 0; i < sizeof(gs_PersistentDatabases); i++) {
  1921. if (gs_PersistentDatabases[i][e_bIsUsed] && gs_PersistentDatabases[i][e_dbDatabase]) {
  1922. db_close@(gs_PersistentDatabases[i][e_dbDatabase]);
  1923. gs_PersistentDatabases[i][e_dbDatabase] = DB:0;
  1924. }
  1925. }
  1926. }
  1927. static stock DB::FindMSB(iInput) {
  1928. // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
  1929. static const
  1930. s_aiDeBruijnBitPositionsPacked[32 char] = {
  1931. 0x0A010900,
  1932. 0x1D02150D,
  1933. 0x12100E0B,
  1934. 0x1E031916,
  1935. 0x1C140C08,
  1936. 0x0718110F,
  1937. 0x06171B13,
  1938. 0x1F04051A
  1939. }
  1940. ;
  1941. if (iInput) {
  1942. #emit LOAD.S.pri iInput
  1943. #emit MOVE.alt
  1944. #emit SHR.C.alt 1
  1945. #emit OR
  1946. #emit MOVE.alt
  1947. #emit SHR.C.alt 2
  1948. #emit OR
  1949. #emit MOVE.alt
  1950. #emit SHR.C.alt 4
  1951. #emit OR
  1952. #emit MOVE.alt
  1953. #emit SHR.C.alt 8
  1954. #emit OR
  1955. #emit MOVE.alt
  1956. #emit SHR.C.alt 16
  1957. #emit OR
  1958. #emit CONST.alt 0x07C4ACDD
  1959. #emit UMUL
  1960. #emit SHR.C.pri 27
  1961. #emit ADD.C s_aiDeBruijnBitPositionsPacked
  1962. #emit LODB.I 1
  1963. #emit RETN
  1964. }
  1965. return -1;
  1966. }
  1967. static stock DB::getstringarg(dest[], arg, len = sizeof (dest)) {
  1968. // Get the address of the previous function's stack. First get the index of
  1969. // the argument required.
  1970. #emit LOAD.S.pri arg
  1971. // Then convert that number to bytes from cells.
  1972. #emit SMUL.C 4
  1973. // Get the previous function's frame. Stored in variable 0 (in the current
  1974. // frame). Parameters are FRM+n+12, locals are FRM-n, previous frame is
  1975. // FRM+0, return address is FRM+4, parameter count is FRM+8. We could add
  1976. // checks that "arg * 4 < *(*(FRM + 0) + 8)", for the previous frame parameter
  1977. // count (in C pointer speak).
  1978. #emit LOAD.S.alt 0
  1979. // Add the frame pointer to the argument offset in bytes.
  1980. #emit ADD
  1981. // Add 12 to skip over the function header.
  1982. #emit ADD.C 12
  1983. // Load the address stored in the specified address.
  1984. #emit LOAD.I
  1985. // Push the length for "strcat".
  1986. #emit PUSH.S len
  1987. // Push the address we just determined was the source.
  1988. #emit PUSH.pri
  1989. // Load the address of the destination.
  1990. #emit LOAD.S.alt dest
  1991. // Blank the first cell so "strcat" behaves like "strcpy".
  1992. #emit CONST.pri 0
  1993. // Store the loaded number 0 to the loaded address.
  1994. #emit STOR.I
  1995. // Push the loaded address.
  1996. #emit PUSH.alt
  1997. // Push the number of parameters passed (in bytes) to the function.
  1998. #emit PUSH.C 12
  1999. // Call the function.
  2000. #emit SYSREQ.C strcat
  2001. // Restore the stack to its level before we called this native.
  2002. #emit STACK 16
  2003. }
  2004. static stock DB::setstringarg(iArg, const szValue[], iLength = sizeof(szValue)) {
  2005. new
  2006. iAddress
  2007. ;
  2008. // Get the address of the previous function's stack. First get the index of
  2009. // the argument required.
  2010. #emit LOAD.S.pri iArg
  2011. // Then convert that number to bytes from cells.
  2012. #emit SMUL.C 4
  2013. // Get the previous function's frame.
  2014. #emit LOAD.S.alt 0
  2015. // Add the frame pointer to the argument offset in bytes.
  2016. #emit ADD
  2017. // Add 12 to skip over the function header.
  2018. #emit ADD.C 12
  2019. // Load the address stored in the specified address.
  2020. #emit LOAD.I
  2021. #emit STOR.S.PRI iAddress
  2022. // Push the length (last argument first)
  2023. #emit PUSH.S iLength
  2024. // Push the new value (source) szValue
  2025. #emit PUSH.S szValue
  2026. // Blank out the first cell of the argument
  2027. #emit CONST.pri 0
  2028. #emit SREF.S.pri iAddress
  2029. // Push the destination
  2030. #emit PUSH.S iAddress
  2031. // Push the number of parameters passed (in bytes) to the function.
  2032. #emit PUSH.C 12
  2033. // Call the function.
  2034. #emit SYSREQ.C strcat
  2035. // Restore the stack to its level before we called this native.
  2036. #emit STACK 16
  2037. }
  2038. // Pretty much Y_Less's va_strlen function
  2039. static stock DB::isargpacked(iArg) {
  2040. // Get the length of the string at the given position on the previous
  2041. // function's stack (convenience function).
  2042. // Get the address of the previous function's stack. First get the index of
  2043. // the argument required.
  2044. #emit LOAD.S.pri iArg
  2045. // Then convert that number to bytes from cells.
  2046. #emit SMUL.C 4
  2047. // Get the previous function's frame. Stored in variable 0 (in the current
  2048. // frame). Parameters are FRM+n+12, locals are FRM-n, previous frame is
  2049. // FRM+0, return address is FRM+4, parameter count is FRM+8. We could add
  2050. // checks that "arg * 4 < *(*(FRM + 0) + 8)", for the previous frame parameter
  2051. // count (in C pointer speak).
  2052. #emit LOAD.S.alt 0
  2053. // Add the frame pointer to the argument offset in bytes.
  2054. #emit ADD
  2055. // Add 12 to skip over the function header.
  2056. #emit ADD.C 12
  2057. // Load the address stored in the specified address.
  2058. #emit LOAD.I
  2059. // Push the address we just determined was the source.
  2060. #emit PUSH.pri
  2061. // Push the number of parameters passed (in bytes) to the function.
  2062. #emit PUSH.C 4
  2063. // Call the function.
  2064. #emit SYSREQ.C ispacked
  2065. // Restore the stack to its level before we called this native.
  2066. #emit STACK 8
  2067. #emit RETN
  2068. // Never called.
  2069. return 0;
  2070. }
  2071. stock DB::GetAmxBaseRelative() {
  2072. static
  2073. s_iAmxBaseRelative = 0
  2074. ;
  2075. if (!s_iAmxBaseRelative) {
  2076. s_iAmxBaseRelative = DB::GetAmxBase();
  2077. #emit LCTRL 1
  2078. #emit LOAD.alt s_iAmxBaseRelative
  2079. #emit ADD
  2080. #emit STOR.pri s_iAmxBaseRelative
  2081. }
  2082. return s_iAmxBaseRelative;
  2083. }
  2084. // By Zeex!
  2085. // Returns the AMX base address i.e. amx->base.
  2086. static stock DB::dummy() {
  2087. return 0;
  2088. }
  2089. stock DB::GetAmxBase() {
  2090. static amx_base = 0; // cached
  2091. if (amx_base == 0) {
  2092. new cod, dat;
  2093. #emit lctrl 0
  2094. #emit stor.s.pri cod
  2095. #emit lctrl 1
  2096. #emit stor.s.pri dat
  2097. // Get code section start address relative to data.
  2098. new code_start = cod - dat;
  2099. // Get address of DB::dummy().
  2100. new fn_addr;
  2101. #emit const.pri DB_dummy
  2102. #emit stor.s.pri fn_addr
  2103. // Get absolute address from the CALL instruction.
  2104. new fn_addr_reloc, call_addr;
  2105. DB_dummy();
  2106. #emit lctrl 6
  2107. #emit stor.s.pri call_addr
  2108. call_addr = call_addr - 12 + code_start;
  2109. #emit lref.s.pri call_addr
  2110. #emit stor.s.pri fn_addr_reloc
  2111. amx_base = fn_addr_reloc - fn_addr - cod;
  2112. }
  2113. return amx_base;
  2114. }
  2115. // phys_memory.inc
  2116. static stock AbsToRel(addr) {
  2117. new dat;
  2118. #emit lctrl 1
  2119. #emit stor.s.pri dat
  2120. return addr - (GetAmxBaseAddress() + dat);
  2121. }
  2122. // This function has a bug in older amx_assembly versions
  2123. static stock WritePhysMemoryCell_(addr, what) {
  2124. new rel_addr = AbsToRel(addr);
  2125. #emit load.s.pri what
  2126. #emit sref.s.pri rel_addr
  2127. #emit stack 4
  2128. #emit retn
  2129. return 0; // make compiler happy
  2130. }
  2131. // Hook db_get_field
  2132. // This is done lastly because the fixed function isn't needed within SQLitei
  2133. #define db_get_field db_get_field_hook
  2134. #define db_get_field_assoc db_get_field_assoc_hook