PageRenderTime 43ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/luamysql/luamysql.cpp

http://luasp.googlecode.com/
C++ | 401 lines | 287 code | 109 blank | 5 comment | 28 complexity | 72ffa019a76ddcbb27bd2f2ee7af67db MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. /*
  2. * Copyright (C) Anton Burdinuk
  3. */
  4. #include "luamysql.h"
  5. #include <mysql.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. namespace libmysql
  10. {
  11. static const char LUA_MYSQL[]="LMYSQL*";
  12. static const char LUA_MYSQL_RESULT[]="LMYSQL_RESULT*";
  13. class membuf
  14. {
  15. public:
  16. char* ptr;
  17. size_t len;
  18. membuf(size_t _len):ptr((char*)malloc(_len)),len(_len) {}
  19. ~membuf(void) {if(ptr) free(ptr);}
  20. };
  21. struct LMYSQL
  22. {
  23. int online;
  24. MYSQL svc;
  25. };
  26. struct LMYSQL_RESULT
  27. {
  28. MYSQL_RES* result;
  29. int fnum;
  30. };
  31. int lua_mysql_open(lua_State* L);
  32. int lua_mysql_close(lua_State* L);
  33. int lua_mysql_gc(lua_State* L);
  34. int lua_mysql_tostring(lua_State* L);
  35. int lua_mysql_escape(lua_State* L);
  36. int lua_mysql_affected_rows(lua_State* L);
  37. int lua_mysql_insert_id(lua_State* L);
  38. int lua_mysql_query(lua_State* L);
  39. int lua_mysql_result_close(lua_State* L);
  40. int lua_mysql_result_gc(lua_State* L);
  41. int lua_mysql_result_tostring(lua_State* L);
  42. int lua_mysql_result_field_count(lua_State* L);
  43. int lua_mysql_result_rows_next(lua_State* L);
  44. int lua_mysql_result_rows(lua_State* L);
  45. int lua_mysql_result_table(lua_State* L);
  46. }
  47. void luaclose_luamysql(void)
  48. {
  49. }
  50. int luaopen_luamysql(lua_State* L)
  51. {
  52. static const luaL_Reg lib[]=
  53. {
  54. {"open",libmysql::lua_mysql_open},
  55. {"close",libmysql::lua_mysql_close},
  56. // connection functions
  57. {"escape",libmysql::lua_mysql_escape},
  58. {"affected_rows",libmysql::lua_mysql_affected_rows},
  59. {"insert_id",libmysql::lua_mysql_insert_id},
  60. {"query",libmysql::lua_mysql_query},
  61. // rowset functions
  62. {"fields_count",libmysql::lua_mysql_result_field_count},
  63. {"rows",libmysql::lua_mysql_result_rows},
  64. {"table",libmysql::lua_mysql_result_table},
  65. {0,0}
  66. };
  67. static const luaL_Reg slib[]=
  68. {
  69. {"__gc",libmysql::lua_mysql_gc},
  70. {"__tostring",libmysql::lua_mysql_tostring},
  71. {"close",libmysql::lua_mysql_close},
  72. {"escape",libmysql::lua_mysql_escape},
  73. {"affected_rows",libmysql::lua_mysql_affected_rows},
  74. {"insert_id",libmysql::lua_mysql_insert_id},
  75. {"query",libmysql::lua_mysql_query},
  76. {0,0}
  77. };
  78. static const luaL_Reg rlib[]=
  79. {
  80. {"__gc",libmysql::lua_mysql_result_gc},
  81. {"__tostring",libmysql::lua_mysql_result_tostring},
  82. {"close",libmysql::lua_mysql_result_close},
  83. {"fields_count",libmysql::lua_mysql_result_field_count},
  84. {"rows",libmysql::lua_mysql_result_rows},
  85. {"table",libmysql::lua_mysql_result_table},
  86. {0,0}
  87. };
  88. luaL_newmetatable(L,libmysql::LUA_MYSQL);
  89. lua_pushvalue(L,-1);
  90. lua_setfield(L,-2,"__index");
  91. luaL_register(L,0,slib);
  92. luaL_newmetatable(L,libmysql::LUA_MYSQL_RESULT);
  93. lua_pushvalue(L,-1);
  94. lua_setfield(L,-2,"__index");
  95. luaL_register(L,0,rlib);
  96. luaL_register(L,"mysql",lib);
  97. #ifdef LUA_MODULE
  98. atexit(luaclose_luamysql);
  99. #endif /*LUA_MODULE*/
  100. return 0;
  101. }
  102. int libmysql::lua_mysql_open(lua_State* L)
  103. {
  104. if(lua_gettop(L)!=2)
  105. return luaL_error(L,"\"mysql.open\" bad params");
  106. const char* condata=luaL_checkstring(L,1);
  107. const char* schema=luaL_checkstring(L,2);
  108. LMYSQL* mysql=(LMYSQL*)lua_newuserdata(L,sizeof(LMYSQL));
  109. luaL_getmetatable(L,LUA_MYSQL);
  110. lua_setmetatable(L,-2);
  111. mysql->online=0;
  112. if(!mysql_init(&mysql->svc))
  113. return luaL_error(L,"mysql_init");
  114. char temp[1024];
  115. int n=snprintf(temp,sizeof(temp),"%s",condata);
  116. if(n<0 || n>=sizeof(temp))
  117. temp[sizeof(temp)-1]=0;
  118. static char null[]="";
  119. char* user=temp;
  120. while(*user && *user==' ') user++;
  121. char* host=strchr(user,'@');
  122. if(!host) { host=user; user=null; } else { *host=0; host++; }
  123. char* pass=strchr(user,':');
  124. if(!pass) pass=null; else { *pass=0; pass++; }
  125. char* port=strchr(host,':');
  126. if(!port) port=null; else { *port=0; port++; }
  127. int _port=atoi(port);
  128. if(_port<0) _port=0;
  129. char* unix_socket=null;
  130. if(*host=='/') { unix_socket=host; host=null; _port=0; }
  131. if(!mysql_real_connect(&mysql->svc,(*host)?host:0,(*user)?user:0,(*pass)?pass:0,schema,_port,(*unix_socket)?unix_socket:0,0))
  132. {
  133. lua_pushstring(L,mysql_error(&mysql->svc));
  134. mysql_close(&mysql->svc);
  135. return lua_error(L);
  136. }
  137. mysql->online=1;
  138. return 1;
  139. }
  140. int libmysql::lua_mysql_close(lua_State* L)
  141. {
  142. LMYSQL* mysql=(LMYSQL*)luaL_checkudata(L,1,LUA_MYSQL);
  143. if(mysql->online)
  144. {
  145. mysql_close(&mysql->svc);
  146. mysql->online=0;
  147. }
  148. return 0;
  149. }
  150. int libmysql::lua_mysql_gc(lua_State* L)
  151. {
  152. return lua_mysql_close(L);
  153. }
  154. int libmysql::lua_mysql_tostring(lua_State* L)
  155. {
  156. LMYSQL* mysql=(LMYSQL*)luaL_checkudata(L,1,LUA_MYSQL);
  157. lua_pushstring(L,mysql->online?"opened":"closed");
  158. return 1;
  159. }
  160. int libmysql::lua_mysql_escape(lua_State* L)
  161. {
  162. LMYSQL* mysql=(LMYSQL*)luaL_checkudata(L,1,LUA_MYSQL);
  163. size_t length=0;
  164. const char* from=luaL_checklstring(L,2,&length);
  165. if(!mysql->online)
  166. {
  167. lua_pushstring(L,"");
  168. return 1;
  169. }
  170. membuf buf(length*2+1);
  171. length=mysql_real_escape_string(&mysql->svc,buf.ptr,from,length);
  172. lua_pushlstring(L,buf.ptr,length);
  173. return 1;
  174. }
  175. int libmysql::lua_mysql_affected_rows(lua_State* L)
  176. {
  177. LMYSQL* mysql=(LMYSQL*)luaL_checkudata(L,1,LUA_MYSQL);
  178. lua_pushinteger(L,mysql->online?mysql_affected_rows(&mysql->svc):0);
  179. return 1;
  180. }
  181. int libmysql::lua_mysql_insert_id(lua_State* L)
  182. {
  183. LMYSQL* mysql=(LMYSQL*)luaL_checkudata(L,1,LUA_MYSQL);
  184. lua_pushinteger(L,mysql->online?mysql_insert_id(&mysql->svc):0);
  185. return 1;
  186. }
  187. int libmysql::lua_mysql_query(lua_State* L)
  188. {
  189. LMYSQL* mysql=(LMYSQL*)luaL_checkudata(L,1,LUA_MYSQL);
  190. size_t len=0;
  191. const char* stmt=luaL_checklstring(L,2,&len);
  192. if(!mysql->online)
  193. return 0;
  194. if(mysql_real_query(&mysql->svc,stmt,len))
  195. {
  196. lua_pushstring(L,mysql_error(&mysql->svc));
  197. return lua_error(L);
  198. }
  199. MYSQL_RES* result=mysql_store_result(&mysql->svc);
  200. if(!result)
  201. return 0;
  202. int fnum=mysql_field_count(&mysql->svc);
  203. if(!fnum)
  204. {
  205. mysql_free_result(result);
  206. return 0;
  207. }
  208. LMYSQL_RESULT* mysql_result=(LMYSQL_RESULT*)lua_newuserdata(L,sizeof(LMYSQL_RESULT));
  209. luaL_getmetatable(L,LUA_MYSQL_RESULT);
  210. lua_setmetatable(L,-2);
  211. mysql_result->result=result;
  212. mysql_result->fnum=fnum;
  213. return 1;
  214. }
  215. int libmysql::lua_mysql_result_close(lua_State* L)
  216. {
  217. LMYSQL_RESULT* mysql_result=(LMYSQL_RESULT*)luaL_checkudata(L,1,LUA_MYSQL_RESULT);
  218. if(mysql_result->result)
  219. {
  220. mysql_free_result(mysql_result->result);
  221. mysql_result->result=0;
  222. }
  223. return 0;
  224. }
  225. int libmysql::lua_mysql_result_gc(lua_State* L)
  226. {
  227. return lua_mysql_result_close(L);
  228. }
  229. int libmysql::lua_mysql_result_tostring(lua_State* L)
  230. {
  231. LMYSQL_RESULT* mysql_result=(LMYSQL_RESULT*)luaL_checkudata(L,1,LUA_MYSQL_RESULT);
  232. char tmp[32]="(nil)";
  233. if(mysql_result->result)
  234. sprintf(tmp,"%i",mysql_result->fnum);
  235. lua_pushstring(L,tmp);
  236. return 1;
  237. }
  238. int libmysql::lua_mysql_result_field_count(lua_State* L)
  239. {
  240. LMYSQL_RESULT* mysql_result=(LMYSQL_RESULT*)luaL_checkudata(L,1,LUA_MYSQL_RESULT);
  241. lua_pushinteger(L,mysql_result->result?mysql_result->fnum:0);
  242. return 1;
  243. }
  244. int libmysql::lua_mysql_result_rows_next(lua_State* L)
  245. {
  246. LMYSQL_RESULT* mysql_result=(LMYSQL_RESULT*)luaL_checkudata(L,lua_upvalueindex(1),LUA_MYSQL_RESULT);
  247. if(!mysql_result->result)
  248. return 0;
  249. MYSQL_ROW row=mysql_fetch_row(mysql_result->result);
  250. if(!row)
  251. return 0;
  252. lua_newtable(L);
  253. for(int i=0;i<mysql_result->fnum;i++)
  254. {
  255. const char* p=row[i];
  256. lua_pushstring(L,p?p:"");
  257. lua_rawseti(L,-2,i+1);
  258. }
  259. return 1;
  260. }
  261. int libmysql::lua_mysql_result_rows(lua_State* L)
  262. {
  263. LMYSQL_RESULT* mysql_result=(LMYSQL_RESULT*)luaL_checkudata(L,1,LUA_MYSQL_RESULT);
  264. if(!mysql_result->result)
  265. return 0;
  266. mysql_data_seek(mysql_result->result,0);
  267. lua_pushvalue(L,-1);
  268. lua_pushcclosure(L,lua_mysql_result_rows_next,1);
  269. return 1;
  270. }
  271. int libmysql::lua_mysql_result_table(lua_State* L)
  272. {
  273. LMYSQL_RESULT* mysql_result=(LMYSQL_RESULT*)luaL_checkudata(L,1,LUA_MYSQL_RESULT);
  274. if(!mysql_result->result)
  275. return 0;
  276. MYSQL_ROW row;
  277. lua_newtable(L);
  278. int j=1;
  279. mysql_data_seek(mysql_result->result,0);
  280. while((row=mysql_fetch_row(mysql_result->result)))
  281. {
  282. lua_newtable(L);
  283. for(int i=0;i<mysql_result->fnum;i++)
  284. {
  285. const char* p=row[i];
  286. lua_pushstring(L,p?p:"");
  287. lua_rawseti(L,-2,i+1);
  288. }
  289. lua_rawseti(L,-2,j++);
  290. }
  291. return 1;
  292. }