Guest User

Untitled

a guest
Nov 24th, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.80 KB | None | 0 0
  1. #include <lua.h>
  2. #include <lauxlib.h>
  3. #include <lualib.h>
  4. #include <mysql/mysql.h>
  5.  
  6. static const char* MySQLLib = "MySQL.lib";
  7. static const char* MySQLResult = "MySQLResult";
  8.  
  9. /* ------------------------------------------------------------------------- */
  10.  
  11. #define mysql_init_error(l, fmt, ...) \
  12. do { \
  13. lua_pushnil(l); /* empty result */ \
  14. lua_pushfstring(l, fmt, ##__VA_ARGS__); /* error message */ \
  15. } while (0)
  16.  
  17. /* return 0 if ok */
  18. static inline int get_args(lua_State* l, const char** host, unsigned int* port,
  19. const char** user, const char** password,
  20. const char** db)
  21. {
  22. int argtype;
  23.  
  24. if (lua_gettop(l) != 1) {
  25. mysql_init_error(l, "1 argument required, but %d is provided.",
  26. lua_gettop(l));
  27. return 2;
  28. }
  29.  
  30. if (!lua_istable(l, 1)) {
  31. mysql_init_error(l, "argument #1 expects a table, but a %s is provided.",
  32. lua_typename(l, lua_type(l, 1)));
  33. return 2;
  34. }
  35.  
  36. lua_getfield(l, 1, "host");
  37. if (!lua_isstring(l, -1)) {
  38. argtype = lua_type(l, -1);
  39. mysql_init_error(l, "argument#1::`host' expects a string, but a %s is provided.",
  40. lua_typename(l, argtype));
  41. return 2;
  42. }
  43. *host = lua_tostring(l, -1);
  44.  
  45. lua_getfield(l, 1, "port");
  46. if (!lua_isnumber(l, -1)) {
  47. argtype = lua_type(l, -1);
  48. mysql_init_error(l, "argument#1::`port' expects a number, but a %s is provided.",
  49. lua_typename(l, argtype));
  50. return 2;
  51. }
  52. *port = lua_tointeger(l, -1);
  53.  
  54. lua_getfield(l, 1, "user");
  55. if (!lua_isnil(l, -1)) {
  56. if (!lua_isstring(l, -1)) {
  57. argtype = lua_type(l, -1);
  58. mysql_init_error(l, "argument#1::`user' expects a string, but a %s is provided.",
  59. lua_typename(l, argtype));
  60. return 2;
  61. }
  62. *user = lua_tostring(l, -1);
  63. }
  64.  
  65. lua_getfield(l, 1, "password");
  66. if (!lua_isnil(l, -1)) {
  67. if (!lua_isstring(l, -1)) {
  68. argtype = lua_type(l, -1);
  69. mysql_init_error(l, "argument#1::`password' expects a string, but a %s is provided.",
  70. lua_typename(l, argtype));
  71. return 2;
  72. }
  73. *password = lua_tostring(l, -1);
  74. }
  75.  
  76. lua_getfield(l, 1, "db");
  77. if (!lua_isnil(l, -1)) {
  78. if (!lua_isstring(l, -1)) {
  79. argtype = lua_type(l, -1);
  80. mysql_init_error(l, "argument#1::`db' expects a string, but a %s is provided.",
  81. lua_typename(l, argtype));
  82. return 2;
  83. }
  84. *db = lua_tostring(l, -1);
  85. }
  86.  
  87. return 0;
  88. }
  89.  
  90. /* return a connection and an error message */
  91. static int l_new_mysqlclient(lua_State* l)
  92. {
  93. MYSQL* conn;
  94. unsigned int port;
  95. const char *host, *user = NULL, *password = NULL, *db = NULL;
  96. const char* errmsg;
  97.  
  98. if (get_args(l, &host, &port, &user, &password, &db) != 0)
  99. return 2;
  100.  
  101. conn = lua_newuserdata(l, sizeof(MYSQL));
  102. luaL_setmetatable(l, MySQLLib);
  103.  
  104. if (!mysql_init(conn)) {
  105. errmsg = "mysql_init() failed.";
  106. goto conn_err;
  107. }
  108.  
  109. if (!mysql_real_connect(conn, host, user, password, db, port, NULL, 0)) {
  110. errmsg = mysql_error(conn);
  111. goto conn_err;
  112. }
  113.  
  114. lua_pushnil(l); /* errmsg */
  115. return 2;
  116.  
  117. conn_err:
  118. lua_pop(l, 1); /* pop the newuserdata */
  119. mysql_init_error(l, errmsg);
  120. return 2;
  121. }
  122.  
  123. /* ------------------------------------------------------------------------- */
  124.  
  125. /* return an error message if fails, otherwise nil */
  126. static int l_mysqlclient_ping(lua_State* l)
  127. {
  128. MYSQL* conn;
  129.  
  130. conn = luaL_testudata(l, 1, MySQLLib);
  131. if (!conn) {
  132. lua_pushstring(l, "argument #1 is not a mysql client.");
  133. return 1;
  134. }
  135.  
  136. if (mysql_ping(conn) == 0)
  137. lua_pushnil(l);
  138. else
  139. lua_pushstring(l, mysql_error(conn));
  140.  
  141. return 1;
  142. }
  143.  
  144. /* return an error message if fails, otherwise nil */
  145. static int l_mysqlclient_selectdb(lua_State* l)
  146. {
  147. MYSQL* conn;
  148. const char* db;
  149.  
  150. conn = luaL_testudata(l, 1, MySQLLib);
  151. if (!conn) {
  152. lua_pushstring(l, "argument #1 is not a mysql client.");
  153. return 1;
  154. }
  155.  
  156. if (!lua_isstring(l, 2)) {
  157. lua_pushfstring(l, "argument #2 expects a db name, but given a %s.",
  158. lua_typename(l, lua_type(l, 2)));
  159. return 1;
  160. }
  161. db = lua_tostring(l, 2);
  162.  
  163. if (mysql_select_db(conn, db) == 0)
  164. lua_pushnil(l);
  165. else
  166. lua_pushstring(l, mysql_error(conn));
  167.  
  168. return 1;
  169. }
  170.  
  171. /* return an error message if fails, otherwise nil */
  172. static int l_mysqlclient_setcharset(lua_State* l)
  173. {
  174. MYSQL* conn;
  175. const char* charset;
  176.  
  177. conn = luaL_testudata(l, 1, MySQLLib);
  178. if (!conn) {
  179. lua_pushstring(l, "argument #1 is not a mysql client.");
  180. return 1;
  181. }
  182.  
  183. if (!lua_isstring(l, 2)) {
  184. lua_pushfstring(l, "argument #2 expects a charset string, but given a %s.",
  185. lua_typename(l, lua_type(l, 2)));
  186. return 1;
  187. }
  188. charset = lua_tostring(l, 2);
  189.  
  190. if (mysql_set_character_set(conn, charset) == 0)
  191. lua_pushnil(l);
  192. else
  193. lua_pushstring(l, mysql_error(conn));
  194.  
  195. return 1;
  196. }
  197.  
  198. /* return the escaped string and the error message */
  199. static int l_mysqlclient_escape(lua_State* l)
  200. {
  201. MYSQL* conn;
  202. const char* content;
  203. char* buf;
  204. luaL_Buffer lbuf;
  205. unsigned long len;
  206.  
  207. conn = luaL_testudata(l, 1, MySQLLib);
  208. if (!conn) {
  209. lua_pushnil(l);
  210. lua_pushstring(l, "argument #1 is not a mysql client.");
  211. return 2;
  212. }
  213.  
  214. if (!lua_isstring(l, 2)) {
  215. int type = lua_type(l, 2);
  216. lua_pushnil(l);
  217. lua_pushfstring(l, "argument #2 expects a sql string, but given a %s.",
  218. lua_typename(l, type));
  219. return 2;
  220. }
  221.  
  222. content = lua_tolstring(l, 2, &len);
  223. if (len == 0) {
  224. lua_pushstring(l, "");
  225. lua_pushnil(l);
  226. return 2;
  227. }
  228.  
  229. buf = luaL_buffinitsize(l, &lbuf, len * 2 + 1);
  230. if (!buf) {
  231. lua_pushnil(l);
  232. lua_pushstring(l, "allocating buffer failed.");
  233. return 2;
  234. }
  235.  
  236. len = mysql_real_escape_string(conn, buf, content, len);
  237. if (len == (unsigned long)(-1)) {
  238. lua_pushnil(l);
  239. luaL_addstring(&lbuf, mysql_error(conn));
  240. luaL_pushresult(&lbuf);
  241. } else {
  242. luaL_pushresultsize(&lbuf, len);
  243. lua_pushnil(l);
  244. }
  245.  
  246. return 2;
  247. }
  248.  
  249. /* return the result set and the error message */
  250. static int l_mysqlclient_query(lua_State* l)
  251. {
  252. int err;
  253. MYSQL* conn;
  254. const char* sqlstr;
  255. unsigned long sqllen;
  256.  
  257. conn = luaL_testudata(l, 1, MySQLLib);
  258. if (!conn) {
  259. lua_pushnil(l);
  260. lua_pushstring(l, "argument #1 is not a mysql client.");
  261. return 2;
  262. }
  263.  
  264. if (!lua_isstring(l, 2)) {
  265. int type = lua_type(l, 2);
  266. lua_pushnil(l);
  267. lua_pushfstring(l, "argument #2 expects a sql string, but given a %s.",
  268. lua_typename(l, type));
  269. return 2;
  270. }
  271. sqlstr = lua_tolstring(l, 2, &sqllen);
  272.  
  273. if (sqllen == 0) {
  274. lua_pushnil(l);
  275. lua_pushstring(l, "invalid SQL statement.");
  276. return 2;
  277. }
  278.  
  279. err = mysql_real_query(conn, sqlstr, sqllen);
  280. if (err) {
  281. lua_pushnil(l);
  282. lua_pushstring(l, mysql_error(conn));
  283. } else {
  284. MYSQL_RES** result = lua_newuserdata(l, sizeof(MYSQL_RES*));
  285. luaL_setmetatable(l, MySQLResult);
  286.  
  287. *result = mysql_store_result(conn);
  288. lua_pushnil(l);
  289. }
  290.  
  291. return 2;
  292. }
  293.  
  294. static int l_mysqlclient_gc(lua_State* l)
  295. {
  296. MYSQL* conn = luaL_testudata(l, 1, MySQLLib);
  297. if (conn)
  298. mysql_close(conn);
  299.  
  300. return 0;
  301. }
  302.  
  303. /* ------------------------------------------------------------------------- */
  304.  
  305. /* return the fieldnamelist, or nil if fails. */
  306. static int l_mysqlresult_fieldnamelist(lua_State* l)
  307. {
  308. MYSQL_RES** result = luaL_testudata(l, 1, MySQLResult);
  309.  
  310. if (!result)
  311. lua_pushnil(l);
  312. else {
  313. int i;
  314. int nr_field = mysql_num_fields(*result);
  315. MYSQL_FIELD* fieldlist = mysql_fetch_fields(*result);
  316.  
  317. lua_newtable(l);
  318. for (i = 0; i < nr_field; ++i) {
  319. lua_pushstring(l, fieldlist[i].name);
  320. lua_rawseti(l, -2, i + 1);
  321. }
  322. }
  323.  
  324. return 1;
  325. }
  326.  
  327. /* return the number of record(s), or nil if fails. */
  328. static int l_mysqlresult_size(lua_State* l)
  329. {
  330. MYSQL_RES** result = luaL_testudata(l, 1, MySQLResult);
  331.  
  332. if (!result)
  333. lua_pushnil(l);
  334. else
  335. lua_pushinteger(l, mysql_num_rows(*result));
  336.  
  337. return 1;
  338. }
  339.  
  340. static int l_mysqlresult_record_iter(lua_State* l)
  341. {
  342. MYSQL_ROW row;
  343. MYSQL_RES** result = lua_touserdata(l, lua_upvalueindex(1));
  344. int nr_field = lua_tointeger(l, lua_upvalueindex(2));
  345.  
  346. row = mysql_fetch_row(*result);
  347. if (row) {
  348. int i;
  349. unsigned long* lengths = mysql_fetch_lengths(*result);
  350.  
  351. lua_newtable(l);
  352. for (i = 0; i < nr_field; ++i) {
  353. lua_pushlstring(l, row[i], lengths[i]);
  354. lua_rawseti(l, -2, i + 1);
  355. }
  356.  
  357. return 1;
  358. }
  359.  
  360. return 0;
  361. }
  362.  
  363. /* return a record iterator, or nil if fails. */
  364. static int l_mysqlresult_recordlist(lua_State* l)
  365. {
  366. MYSQL_RES** result = luaL_testudata(l, 1, MySQLResult);
  367.  
  368. if (!result)
  369. lua_pushnil(l);
  370. else {
  371. lua_pushvalue(l, -1); /* duplicate the result */
  372. lua_pushinteger(l, mysql_num_fields(*result)); /* number of fields */
  373. lua_pushcclosure(l, l_mysqlresult_record_iter, 2);
  374. }
  375.  
  376. return 1;
  377. }
  378.  
  379. static int l_mysqlresult_gc(lua_State* l)
  380. {
  381. MYSQL_RES** result = luaL_testudata(l, 1, MySQLResult);
  382.  
  383. if (*result)
  384. mysql_free_result(*result);
  385.  
  386. return 0;
  387. }
  388.  
  389. /* ------------------------------------------------------------------------- */
  390.  
  391. static const struct luaL_Reg mysqlclient_f[] = {
  392. {"newclient", l_new_mysqlclient},
  393. {NULL, NULL},
  394. };
  395.  
  396. static const struct luaL_Reg mysqlclient_m[] = {
  397. {"ping", l_mysqlclient_ping},
  398. {"selectdb", l_mysqlclient_selectdb},
  399. {"setcharset", l_mysqlclient_setcharset},
  400. {"escape", l_mysqlclient_escape},
  401. {"query", l_mysqlclient_query},
  402. {"__gc", l_mysqlclient_gc},
  403. {NULL, NULL},
  404. };
  405.  
  406. static const struct luaL_Reg mysqlresult_lib[] = {
  407. {"size", l_mysqlresult_size},
  408. {"fieldnamelist", l_mysqlresult_fieldnamelist},
  409. {"recordlist", l_mysqlresult_recordlist},
  410. {"__gc", l_mysqlresult_gc},
  411. {NULL, NULL},
  412. };
  413.  
  414. int luaopen_luamysql(lua_State* l)
  415. {
  416. /* meta table for mysql client */
  417. luaL_newmetatable(l, MySQLLib);
  418. lua_pushvalue(l, -1);
  419. lua_setfield(l, -2, "__index");
  420. luaL_setfuncs(l, mysqlclient_m, 0);
  421.  
  422. /* meta table for mysql result */
  423. luaL_newmetatable(l, MySQLResult);
  424. lua_pushvalue(l, -1);
  425. lua_setfield(l, -2, "__index");
  426. luaL_setfuncs(l, mysqlresult_lib, 0);
  427.  
  428. luaL_newlib(l, mysqlclient_f);
  429. return 1;
  430. }
Add Comment
Please, Sign In to add comment