1
0

sql.inc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /**
  2. * Copyright (c) 2013, Dan
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  18. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. /**
  26. * <version>2.6</version>
  27. * <remarks>
  28. * Data types:
  29. * SQL - a SQL database handle
  30. * Result - the result of a query, whether it returns or not rows
  31. * </remarks>
  32. */
  33. /**
  34. * <summary>MySQL client error codes.</summary>
  35. */
  36. #define MYSQL_CR_UNKNOWN_ERROR 2000
  37. #define MYSQL_CR_SOCKET_CREATE_ERROR 2001
  38. #define MYSQL_CR_CONNECTION_ERROR 2002
  39. #define MYSQL_CR_CONN_HOST_ERROR 2003
  40. #define MYSQL_CR_IPSOCK_ERROR 2004
  41. #define MYSQL_CR_UNKNOWN_HOST 2005
  42. #define MYSQL_CR_SERVER_GONE_ERROR 2006
  43. #define MYSQL_CR_VERSION_ERROR 2007
  44. #define MYSQL_CR_OUT_OF_MEMORY 2008
  45. #define MYSQL_CR_WRONG_HOST_INFO 2009
  46. #define MYSQL_CR_LOCALHOST_CONNECTION 2010
  47. #define MYSQL_CR_TCP_CONNECTION 2011
  48. #define MYSQL_CR_SERVER_HANDSHAKE_ERR 2012
  49. #define MYSQL_CR_SERVER_LOST 2013
  50. #define MYSQL_CR_COMMANDS_OUT_OF_SYNC 2014
  51. #define MYSQL_CR_NAMEDPIPE_CONNECTION 2015
  52. #define MYSQL_CR_NAMEDPIPEWAIT_ERROR 2016
  53. #define MYSQL_CR_NAMEDPIPEOPEN_ERROR 2017
  54. #define MYSQL_CR_NAMEDPIPESETSTATE_ERROR 2018
  55. #define MYSQL_CR_CANT_READ_CHARSET 2019
  56. #define MYSQL_CR_NET_PACKET_TOO_LARGE 2020
  57. #define MYSQL_CR_EMBEDDED_CONNECTION 2021
  58. #define MYSQL_CR_PROBE_SLAVE_STATUS 2022
  59. #define MYSQL_CR_PROBE_SLAVE_HOSTS 2023
  60. #define MYSQL_CR_PROBE_SLAVE_CONNECT 2024
  61. #define MYSQL_CR_PROBE_MASTER_CONNECT 2025
  62. #define MYSQL_CR_SSL_CONNECTION_ERROR 2026
  63. #define MYSQL_CR_MALFORMED_PACKET 2027
  64. #define MYSQL_CR_WRONG_LICENSE 2028
  65. #define MYSQL_CR_NULL_POINTER 2029
  66. #define MYSQL_CR_NO_PREPARE_STMT 2030
  67. #define MYSQL_CR_PARAMS_NOT_BOUND 2031
  68. #define MYSQL_CR_DATA_TRUNCATED 2032
  69. #define MYSQL_CR_NO_PARAMETERS_EXISTS 2033
  70. #define MYSQL_CR_INVALID_PARAMETER_NO 2034
  71. #define MYSQL_CR_INVALID_BUFFER_USE 2035
  72. #define MYSQL_CR_UNSUPPORTED_PARAM_TYPE 2036
  73. #define MYSQL_CR_SHARED_MEMORY_CONNECTION 2037
  74. #define MYSQL_CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2038
  75. #define MYSQL_CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2039
  76. #define MYSQL_CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2040
  77. #define MYSQL_CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2041
  78. #define MYSQL_CR_SHARED_MEMORY_FILE_MAP_ERROR 2042
  79. #define MYSQL_CR_SHARED_MEMORY_MAP_ERROR 2043
  80. #define MYSQL_CR_SHARED_MEMORY_EVENT_ERROR 2044
  81. #define MYSQL_CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR 2045
  82. #define MYSQL_CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046
  83. #define MYSQL_CR_CONN_UNKNOW_PROTOCOL 2047
  84. #define MYSQL_CR_INVALID_CONN_HANDLE 2048
  85. #define MYSQL_CR_SECURE_AUTH 2049
  86. #define MYSQL_CR_FETCH_CANCELED 2050
  87. #define MYSQL_CR_NO_DATA 2051
  88. #define MYSQL_CR_NO_STMT_METADATA 2052
  89. /**
  90. * <summary>MySQL</summary>
  91. */
  92. #define SQL_HANDLER_MYSQL 1
  93. /**
  94. * <summary>Postgre SQL</summary>
  95. */
  96. #define SQL_HANDLER_POSTGRESQL 2
  97. /**
  98. * <summary>The query will be executed in server's thread and the result is fetched on demand.</summary>
  99. */
  100. #define QUERY_NONE 0
  101. /**
  102. * <summary>Runs the query in a different thread (other than main server's thread).</summary>
  103. */
  104. #define QUERY_THREADED 1
  105. /**
  106. * <summary>Stores (temporarily) rows returned by a query in cache.</summary>
  107. */
  108. #define QUERY_CACHED 2
  109. /**
  110. * <summary>Log levels. (@see sql_debug)</summary>
  111. */
  112. #define LOG_ALL 0
  113. #define LOG_DEBUG 1
  114. #define LOG_INFO 2
  115. #define LOG_WARNING 3
  116. #define LOG_ERROR 4
  117. #define LOG_NONE 5
  118. /**
  119. * <summary>Checks if a string is null.</summary>
  120. */
  121. #if !defined isnull
  122. #define isnull(%1) \
  123. ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
  124. #endif
  125. /**
  126. * <summary>Checks if a cell from a SQL table is null.</summary>
  127. */
  128. #if !defined issqlnull
  129. #define issqlnull(%1) \
  130. ((isnull(%1)) || (strcmp(%1, "NULL", false) == 0))
  131. #endif
  132. /**
  133. * <summary>Aliases of natives defined below.</summary>
  134. */
  135. #define sql_open sql_connect
  136. #define sql_close sql_disconnect
  137. #define mysql_connect(%0) sql_connect(SQL_HANDLER_MYSQL,%0)
  138. #define pgsql_connect(%0) sql_connect(SQL_HANDLER_POSTGRESQL,%0)
  139. /**
  140. * <summary>Called when a SQL error occurs during the execution of a query.</summary>
  141. * <param name="handle">The SQL handle used for execution of the query.</param>
  142. * <param name="errorid">The ID of the error (@see "C.4. Client Error Codes and Messages" from "SQL Reference Manual").</param>
  143. * <param name="error">The message of the error.</param>
  144. * <param name="query">Query which caused the error.</param>
  145. * <param name="callback">Callback which should have been called normally.</param>
  146. * <returns>No return value is expected.</returns>
  147. */
  148. forward OnSQLError(SQL:handle, errorid, error[], query[], callback[]);
  149. /**
  150. * <summary>Sets the minimum level of logged messages.</summary>
  151. * <param name="file">The minimum level of the file (sql_log.txt) logs.</param>
  152. * <param name="console">The minimum level of the console logs.</param>
  153. * <returns>No return value.</returns>
  154. */
  155. native sql_debug(file = LOG_ALL, console = LOG_WARNING);
  156. /**
  157. * <summary>Creates a new handle and connects to a SQL server.</summary>
  158. * <param name="host">The SQL hostname.</param>
  159. * <param name="user">The SQL username.</param>
  160. * <param name="pass">The SQL password assigned to the user used.</param>
  161. * <param name="db">The name of the targeted database.</param>
  162. * <param name="port">The port on which the SQL server listens.</param>
  163. * <returns>The ID of the handle.</returns>
  164. */
  165. native SQL:sql_connect(sql_type, host[], user[], pass[], db[], port = 0);
  166. /**
  167. * <summary>Destroys the handle and disconnects from the SQL server.</summary>
  168. * <param name="handle">The SQL handle which has to be disconnected.</param>
  169. * <returns>No return value.</returns>
  170. */
  171. native sql_disconnect(SQL:handle);
  172. /**
  173. * <summary>Waits for a handle to finish its activity (all queries to be executed).</summary>
  174. * <param name="handle">The SQL handle.</param>
  175. * <returns>No return value.</returns>
  176. */
  177. native sql_wait(SQL:handle);
  178. /**
  179. * <summary>Sets default character set.</summary>
  180. * <param name="handle">The SQL handle.</param>
  181. * <param name="charset">New default character set.</param>
  182. * <returns>True if succesful.</returns>
  183. */
  184. native sql_set_charset(SQL:handle, charset[]);
  185. /**
  186. * <summary>Gets default character set.</summary>
  187. * <param name="dest">The destination where the character set will be stored.</param>
  188. * <param name="dest_len">The capacity of the destination.</param>
  189. * <returns>True if succesful.</returns>
  190. */
  191. native sql_get_charset(SQL:handle, dest[], dest_len = sizeof(dest));
  192. /**
  193. * <summary>Pings the SQL server.</summary>
  194. * <param name="handle">The SQL handle which has to be disconnected.</param>
  195. * <returns>Returns a SQL client error (if any) or 0 if the connection is alive.</returns>
  196. */
  197. native sql_ping(SQL:handle);
  198. /**
  199. * <summary>Gets statistics from SQL server.</summary>
  200. * <param name="dest">The destination where the information will be stored.</param>
  201. * <param name="dest_len">The capacity of the destination.</param>
  202. * <returns>True if succesful.</returns>
  203. */
  204. native sql_get_stat(SQL:handle, dest[], dest_len = sizeof(dest));
  205. /**
  206. * <summary>Escapes a string to be used further in queries.</summary>
  207. * <param name="handle">The SQL handle used for escaping the string.</param>
  208. * <param name="src">The source of the unescaped string.</param>
  209. * <param name="dest">The destination where the escaped string will be stored.</param>
  210. * <param name="dest_len">The capacity of the destination.</param>
  211. * <returns>The length of the escaped string.</returns>
  212. */
  213. native sql_escape_string(SQL:handle, src[], dest[], dest_len = sizeof(dest));
  214. /**
  215. * <summary>Executes a SQL query and returns the result.</summary>
  216. * <param name="handle">The SQL handle used for execution of the query.</param>
  217. * <param name="query">The query.</param>
  218. * <param name="flag">Query's flags.</param>
  219. * <param name="callback">The callback which has to be called after the query was sucesfully executed.</param>
  220. * <param name="format">The format of the callback.
  221. * a, A = arrays (must be followed by an integer: array's szie);
  222. * b, B = boolean; c, C = character; d, D, i, I = integer;
  223. * r, R = result; s, S = string
  224. * </param>
  225. * <returns>The ID of the result.</returns>
  226. */
  227. native Result:sql_query(SQL:handle, query[], flag = QUERY_NONE, callback[] = "", format[] = "", {Float,_}:...);
  228. /**
  229. * <summary>Stores the result for later use (if query is threaded).</summary>
  230. * <param name="result">The ID of the result which has to be stored.</param>
  231. * <returns>No return value.</returns>
  232. */
  233. native sql_store_result(Result:result);
  234. /**
  235. * <summary>Frees the result for later use (if the query was stored or is not threaded).</summary>
  236. * <param name="result">The ID of the result which has to be freed.</param>
  237. * <returns>No return value.</returns>
  238. */
  239. native sql_free_result(Result:result);
  240. /**
  241. * <summary>Gets the count of affected rows.</summary>
  242. * <param name="result">The ID of the result.</param>
  243. * <returns>The count of affected rows.</returns>
  244. */
  245. native sql_affected_rows(Result:result);
  246. /**
  247. * <summary>Gets the ID of the last insert query.</summary>
  248. * <param name="result">The ID of the result.</param>
  249. * <returns>The ID of the latest inserted row.</returns>
  250. */
  251. native sql_insert_id(Result:result);
  252. /**
  253. * <summary>Gets the ID of the error returned by this result.</summary>
  254. * <param name="result">The ID of the result.</param>
  255. * <returns>The ID of the error.</returns>
  256. */
  257. native sql_error(Result:result);
  258. /**
  259. * <summary>Gets the message of the error returned by this result.</summary>
  260. * <param name="result">The ID of the result.</param>
  261. * <param name="dest">The destination where the error message will be stored.</param>
  262. * <param name="dest_len">The capacity of the destination.</param>
  263. * <returns>The ID of the error.</returns>
  264. */
  265. native sql_error_string(Result:result, dest[], dest_len = sizeof(dest));
  266. /**
  267. * <summary>Gets the count of rows contained in a result.</summary>
  268. * <param name="result">The ID of the result.</param>
  269. * <returns>The count of rows contained in the result.</returns>
  270. */
  271. native sql_num_rows(Result:result);
  272. /**
  273. * <summary>Gets the count of fields contained in a result.</summary>
  274. * <param name="result">The ID of the result.</param>
  275. * <returns>The count of fields contained in the result.</returns>
  276. */
  277. native sql_num_fields(Result:result);
  278. /**
  279. * <summary>Jumps to a specific result set.</summary>
  280. * <param name="result">The ID of the result.</param>
  281. * <param name="idx">The index of the result set. If -1 is specified, next result set will be retrieved.</param>
  282. * <returns>`true` if there are any results left, `false` otherwise.</returns>
  283. */
  284. native sql_next_result(Result:result, idx = -1);
  285. /**
  286. * <summary>Fetches the name of a field.</summary>
  287. * <param name="result">The ID of the result.</param>
  288. * <param name="field">The index of the field.</param>
  289. * <param name="dest">The destination where the field will be stored.</param>
  290. * <param name="dest_len">The capacity of the destination.</param>
  291. * <returns>The length of field's name.</returns>
  292. */
  293. native sql_field_name(Result:result, field, dest[], dest_len = sizeof(dest));
  294. /**
  295. * <summary>Fetches an entire row inserting the separator between each cell.</summary>
  296. * <param name="result"></param>
  297. * <param name="separator"></param>
  298. * <param name="dest">The destination where the field will be stored.</param>
  299. * <param name="dest_len">The capacity of the destination.</param>
  300. * <returns>The length of the row.</returns>
  301. */
  302. native sql_fetch_row(Result:result, sep[], dest[], dest_len = sizeof(dest));
  303. /**
  304. * <summary>Jumps to a specific row.</summary>
  305. * <param name="result">The ID of the result.</param>
  306. * <param name="row">The index of the row. If -1 is specified, next row will be retrieved.</param>
  307. * <returns>`true` if there are any rows left, `false` otherwise.</returns>
  308. */
  309. native sql_next_row(Result:result, row = -1);
  310. // ----------------------------------------------------------------------------
  311. /**
  312. * <summary>Fetches a cell containing a string by field index.</summary>
  313. * <param name="result">The ID of the result.</param>
  314. * <param name="field">The index of the field.</param>
  315. * <param name="dest">The destination where the string will be stored.</param>
  316. * <param name="dest_len">The capacity of the destination.</param>
  317. * <returns>The length of the string.</returns>
  318. */
  319. native sql_get_field(Result:result, field, dest[], dest_len = sizeof(dest));
  320. /**
  321. * <summary>Fetches a cell containing a string by field name.</summary>
  322. * <param name="result">The ID of the result.</param>
  323. * <param name="field">The name of the field.</param>
  324. * <param name="dest">The destination where the string will be stored.</param>
  325. * <param name="dest_len">The capacity of the destination.</param>
  326. * <returns>The length of the string.</returns>
  327. */
  328. native sql_get_field_assoc(Result:result, field[], dest[], dest_len = sizeof(dest));
  329. /**
  330. * <summary>Fetches a cell containing an integer value by field index.</summary>
  331. * <param name="result">The ID of the result.</param>
  332. * <param name="field">The index of the field.</param>
  333. * <returns>The value of the cell.</returns>
  334. */
  335. native sql_get_field_int(Result:result, field);
  336. /**
  337. * <summary>Fetches a cell containing an integer value by field name.</summary>
  338. * <param name="result">The ID of the result.</param>
  339. * <param name="field">The name of the field.</param>
  340. * <returns>The value of the cell.</returns>
  341. */
  342. native sql_get_field_assoc_int(Result:result, field[]);
  343. /**
  344. * <summary>Fetches a cell containing a float value by field index.</summary>
  345. * <param name="result">The ID of the result.</param>
  346. * <param name="field">The index of the field.</param>
  347. * <returns>The value of the cell.</returns>
  348. */
  349. native Float:sql_get_field_float(Result:result, field);
  350. /**
  351. * <summary>Fetches a cell containing a float value by field name.</summary>
  352. * <param name="result">The ID of the result.</param>
  353. * <param name="field">The name of the field.</param>
  354. * <returns>The value of the cell.</returns>
  355. */
  356. native Float:sql_get_field_assoc_float(Result:result, field[]);
  357. // ----------------------------------------------------------------------------
  358. /**
  359. * <summary>Fetches a cell containing a string by field index.</summary>
  360. * <param name="result">The ID of the result.</param>
  361. * <param name="row">The index of the row.</param>
  362. * <param name="field">The index of the field.</param>
  363. * <param name="dest">The destination where the string will be stored.</param>
  364. * <param name="dest_len">The capacity of the destination.</param>
  365. * <returns>The length of the string.</returns>
  366. */
  367. native sql_get_field_ex(Result:result, row, field, dest[], dest_len = sizeof(dest));
  368. /**
  369. * <summary>Fetches a cell containing a string by field name.</summary>
  370. * <param name="result">The ID of the result.</param>
  371. * <param name="row">The index of the row.</param>
  372. * <param name="field">The name of the field.</param>
  373. * <param name="dest">The destination where the string will be stored.</param>
  374. * <param name="dest_len">The capacity of the destination.</param>
  375. * <returns>The length of the string.</returns>
  376. */
  377. native sql_get_field_assoc_ex(Result:result, row, field[], dest[], dest_len = sizeof(dest));
  378. /**
  379. * <summary>Fetches a cell containing an integer value by field index.</summary>
  380. * <param name="result">The ID of the result.</param>
  381. * <param name="row">The index of the row.</param>
  382. * <param name="field">The index of the field.</param>
  383. * <returns>The value of the cell.</returns>
  384. */
  385. native sql_get_field_int_ex(Result:result, row, field);
  386. /**
  387. * <summary>Fetches a cell containing an integer value by field name.</summary>
  388. * <param name="result">The ID of the result.</param>
  389. * <param name="row">The index of the row.</param>
  390. * <param name="field">The name of the field.</param>
  391. * <returns>The value of the cell.</returns>
  392. */
  393. native sql_get_field_assoc_int_ex(Result:result, row, field[]);
  394. /**
  395. * <summary>Fetches a cell containing a float value by field index.</summary>
  396. * <param name="result">The ID of the result.</param>
  397. * <param name="row">The index of the row.</param>
  398. * <param name="field">The index of the field.</param>
  399. * <returns>The value of the cell.</returns>
  400. */
  401. native Float:sql_get_field_float_ex(Result:result, row, field);
  402. /**
  403. * <summary>Fetches a cell containing a float value by field name.</summary>
  404. * <param name="result">The ID of the result.</param>
  405. * <param name="row">The index of the row.</param>
  406. * <param name="field">The name of the field.</param>
  407. * <returns>The value of the cell.</returns>
  408. */
  409. native Float:sql_get_field_assoc_float_ex(Result:result, row, field[]);
  410. // ----------------------------------------------------------------------------
  411. /**
  412. * y_inline interface
  413. */
  414. #if !defined SQL_USE_Y_INLINE
  415. // NOTE: #emit ignores pre-processor's directives.
  416. // So, if we disable y_inline support, the #emit instructions below still
  417. // requirea variable to store the address of the first passed parameter.
  418. new SQL_addr;
  419. #pragma unused SQL_addr
  420. #endif
  421. #if defined SQL_USE_Y_INLINE
  422. #if !defined SQL_MAX_INLINE_CALLBACKS
  423. /**
  424. * <summary>The maximum number of inline callbacks scheduled simultaneously.</summary>
  425. */
  426. #define SQL_MAX_INLINE_CALLBACKS 512
  427. #endif
  428. #if !defined SQL_MAX_INLINE_PARAMETERS
  429. /**
  430. * <summary>The maximum number of parameters an inline function can have.</summary>
  431. */
  432. #define SQL_MAX_INLINE_PARAMETERS 16
  433. #endif
  434. /**
  435. * <summary>Executes a SQL query and calls an inline callback on return.</summary>
  436. * <remarks>The "format" parameter must be static.</remarks>
  437. */
  438. //native Result:sql_query_inline(SQL:handle, query[], flag, callback:callback, format[] = "", {Float,_}:...);
  439. #define sql_query_inline(%0,%1,%2,%3,"%4"%5) \
  440. sql_query(%0,%1,%2,"SQL_OnInlineCallback","i"#%4,SQL_SaveCallback(%3)%5)
  441. /**
  442. * <summary>Stores information about callbacks that are scheduled to be executed.</summary>
  443. * <remarks>This data is recycled. Once `SQL_LoadCallback` was called, that index is marked as free.</remarks>
  444. *
  445. * TODO: If the query fails, the `SQL_OnInlineCallback` won't be called
  446. * and the data won't be recycled. Fix it.
  447. */
  448. stock SQL_callbacks[SQL_MAX_INLINE_CALLBACKS][E_CALLBACK_DATA];
  449. /**
  450. * <summary>Saves the callback data of a scheduled statement.</summary>
  451. * <param name="callback">Callback's ID.</param>
  452. * <returns>The index from `SQL_callbacks` where the callback was saved.</returns>
  453. */
  454. stock SQL_SaveCallback(callback:callback) {
  455. for (new i = 0; i != sizeof(SQL_callbacks); ++i) {
  456. if (SQL_callbacks[i][E_CALLBACK_DATA_POINTER] != 0) {
  457. continue;
  458. }
  459. if (!Callback_Get(callback, SQL_callbacks[i])) {
  460. SQL_callbacks[i][E_CALLBACK_DATA_POINTER] = 0;
  461. return -1;
  462. }
  463. return i;
  464. }
  465. print("[plugin.sql][warning] No more free space in `SQL_callbacks`.");
  466. return -1;
  467. }
  468. /**
  469. * <summary>The Interface between the plugin and y_inline, which loads the callback data and executes it.</summary>
  470. * <remarks>This function also recycles data.</remarks>
  471. * <param name="idx">Callback's index from `SQL_callbacks`.</param>
  472. */
  473. forward SQL_OnInlineCallback(idx, {Float,_}:...);
  474. public SQL_OnInlineCallback(idx, {Float,_}:...) {
  475. if (idx == -1) {
  476. return;
  477. }
  478. new numArgs = numargs(), SQL_addr[SQL_MAX_INLINE_PARAMETERS];
  479. if (numArgs > 1) {
  480. #emit CONST.alt 16
  481. #emit LCTRL 5
  482. #emit ADD
  483. #emit STOR.S.pri SQL_addr
  484. --numArgs;
  485. for (new i = 1; i != numArgs; ++i) {
  486. SQL_addr[i] = SQL_addr[0] + (i * 4); // BYTES_PER_CELL = 4
  487. }
  488. }
  489. Callback_Array(SQL_callbacks[idx], SQL_addr);
  490. SQL_callbacks[idx][E_CALLBACK_DATA_POINTER] = 0;
  491. }
  492. #endif