1
4
5# include "luametatex.h"
6# include "lmtoptional.h"
7
8typedef void mysql_instance;
9typedef void mysql_result;
10typedef char **mysql_row;
11typedef unsigned int mysql_offset;
12
13typedef struct mysql_field {
14 char *name;
15 char *org_name;
16 char *table;
17 char *org_table;
18 char *db;
19 char *catalog;
20 char *def;
21 unsigned long length;
22 unsigned long max_length;
23 unsigned int name_length;
24 unsigned int org_name_length;
25 unsigned int table_length;
26 unsigned int org_table_length;
27 unsigned int db_length;
28 unsigned int catalog_length;
29 unsigned int def_length;
30 unsigned int flags;
31 unsigned int decimals;
32 unsigned int charsetnr;
33 int type;
34 void *extension;
35} mysql_field;
36
37# define MYSQLLIB_METATABLE "luatex.mysqllib"
38
39typedef struct mysqllib_data {
40
41 mysql_instance * db;
42} mysqllib_data ;
43
44typedef struct mysqllib_state_info {
45
46 int initialized;
47 int padding;
48
49 mysql_instance * (*mysql_init) (
50 mysql_instance *mysql
51 );
52
53 mysql_instance * (*mysql_real_connect) (
54 mysql_instance *mysql,
55 const char *host,
56 const char *user,
57 const char *passwd,
58 const char *db,
59 unsigned int port,
60 const char *unix_socket,
61 unsigned long clientflag
62 );
63
64 unsigned int (*mysql_errno) (
65 mysql_instance *mysql
66 );
67
68 const char * (*mysql_error) (
69 mysql_instance *mysql
70 );
71
72 int (*mysql_real_query) (
73 mysql_instance *mysql,
74 const char *q,
75 unsigned long length
76 );
77
78 mysql_result * (*mysql_store_result) (
79 mysql_instance *mysql
80 );
81
82 void (*mysql_free_result) (
83 mysql_result *result
84 );
85
86 unsigned long long (*mysql_num_rows) (
87 mysql_result *res
88 );
89
90 mysql_row (*mysql_fetch_row) (
91 mysql_result *result
92 );
93
94 unsigned int (*mysql_affected_rows) (
95 mysql_instance *mysql
96 );
97
98 unsigned int (*mysql_field_count) (
99 mysql_instance *mysql
100 );
101
102 unsigned int (*mysql_num_fields) (
103 mysql_result *res
104 );
105
106 mysql_field * (*mysql_fetch_fields) (
107 mysql_result *res
108 );
109
110 mysql_offset (*mysql_field_seek) (
111 mysql_result *result,
112 mysql_offset offset
113 );
114
115 void (*mysql_close) (
116 mysql_instance *sock
117 );
118
119} mysqllib_state_info;
120
121static mysqllib_state_info mysqllib_state = {
122
123 .initialized = 0,
124 .padding = 0,
125
126 .mysql_init = NULL,
127 .mysql_real_connect = NULL,
128 .mysql_errno = NULL,
129 .mysql_error = NULL,
130 .mysql_real_query = NULL,
131 .mysql_store_result = NULL,
132 .mysql_free_result = NULL,
133 .mysql_num_rows = NULL,
134 .mysql_fetch_row = NULL,
135 .mysql_affected_rows = NULL,
136 .mysql_field_count = NULL,
137 .mysql_num_fields = NULL,
138 .mysql_fetch_fields = NULL,
139 .mysql_field_seek = NULL,
140 .mysql_close = NULL,
141
142};
143
144static int mysqllib_initialize(lua_State * L)
145{
146 if (! mysqllib_state.initialized) {
147 const char *filename = lua_tostring(L, 1);
148 if (filename != NULL) {
149
150 lmt_library lib = lmt_library_load(filename);
151
152 mysqllib_state.mysql_init = lmt_library_find(lib, "mysql_init" );
153 mysqllib_state.mysql_real_connect = lmt_library_find(lib, "mysql_real_connect" );
154 mysqllib_state.mysql_errno = lmt_library_find(lib, "mysql_errno" );
155 mysqllib_state.mysql_error = lmt_library_find(lib, "mysql_error" );
156 mysqllib_state.mysql_real_query = lmt_library_find(lib, "mysql_real_query" );
157 mysqllib_state.mysql_store_result = lmt_library_find(lib, "mysql_store_result" );
158 mysqllib_state.mysql_free_result = lmt_library_find(lib, "mysql_free_result" );
159 mysqllib_state.mysql_num_rows = lmt_library_find(lib, "mysql_num_rows" );
160 mysqllib_state.mysql_fetch_row = lmt_library_find(lib, "mysql_fetch_row" );
161 mysqllib_state.mysql_affected_rows = lmt_library_find(lib, "mysql_affected_rows" );
162 mysqllib_state.mysql_field_count = lmt_library_find(lib, "mysql_field_count" );
163 mysqllib_state.mysql_num_fields = lmt_library_find(lib, "mysql_num_fields" );
164 mysqllib_state.mysql_fetch_fields = lmt_library_find(lib, "mysql_fetch_fields" );
165 mysqllib_state.mysql_field_seek = lmt_library_find(lib, "mysql_field_seek" );
166 mysqllib_state.mysql_close = lmt_library_find(lib, "mysql_close" );
167
168 mysqllib_state.initialized = lmt_library_okay(lib);
169 }
170 }
171 lua_pushboolean(L, mysqllib_state.initialized);
172 return 1;
173}
174
175static int mysqllib_open(lua_State * L)
176{
177 if (mysqllib_state.initialized) {
178 const char * database = luaL_checkstring(L, 1);
179 const char * username = luaL_optstring(L, 2, NULL);
180 const char * password = luaL_optstring(L, 3, NULL);
181 const char * host = luaL_optstring(L, 4, NULL);
182 int port = lmt_optinteger(L, 5, 0);
183 const char * socket = NULL;
184 int flag = 0;
185 mysql_instance * db = mysqllib_state.mysql_init(NULL);
186 if (db != NULL) {
187 if (mysqllib_state.mysql_real_connect(db, host, username, password, database, port, socket, flag)) {
188 mysqllib_data *data = lua_newuserdatauv(L, sizeof(data), 0);
189 data->db = db ;
190 luaL_getmetatable(L, MYSQLLIB_METATABLE);
191 lua_setmetatable(L, -2);
192 return 1;
193 } else {
194 mysqllib_state.mysql_close(db);
195 }
196 }
197 }
198 return 0;
199}
200
201static int mysqllib_close(lua_State * L)
202{
203 if (mysqllib_state.initialized) {
204 mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
205 if (data != NULL) {
206 mysqllib_state.mysql_close(data->db);
207 data->db = NULL;
208 }
209 }
210 return 0;
211}
212
213
214
215static int mysqllib_execute(lua_State * L)
216{
217 if (mysqllib_state.initialized) {
218 mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
219 if (data != NULL) {
220 size_t length = 0;
221 const char *query = lua_tolstring(L, 2, &length);
222 if (query != NULL) {
223 int error = mysqllib_state.mysql_real_query(data->db, query, (int) length);
224 if (!error) {
225 mysql_result * result = mysqllib_state.mysql_store_result(data->db);
226 if (result != NULL) {
227 int nofrows = 0;
228 int nofcolumns = 0;
229 mysqllib_state.mysql_field_seek(result, 0);
230 nofrows = (int) mysqllib_state.mysql_num_rows(result);
231 nofcolumns = mysqllib_state.mysql_num_fields(result);
232
233 if (nofcolumns > 0 && nofrows > 0) {
234 for (int r = 0; r < nofrows; r++) {
235 mysql_row row = mysqllib_state.mysql_fetch_row(result);
236 lua_pushvalue(L, -1);
237 lua_pushinteger(L, nofcolumns);
238 lua_createtable(L, nofcolumns, 0);
239 for (int c = 0; c < nofcolumns; c++) {
240 lua_pushstring(L, row[c]);
241 lua_rawseti(L, -2, (lua_Integer)c + 1);
242 }
243 if (r) {
244 lua_call(L, 2, 0);
245 } else {
246 mysql_field * fields = mysqllib_state.mysql_fetch_fields(result);
247 lua_createtable(L, nofcolumns, 0);
248 for (int c = 0; c < nofcolumns; c++) {
249 lua_pushstring(L, fields[c].name);
250 lua_rawseti(L, -2, (lua_Integer)c + 1);
251 }
252 lua_call(L, 3, 0);
253 }
254 }
255 }
256 mysqllib_state.mysql_free_result(result);
257 }
258 lua_pushboolean(L, 1);
259 return 1;
260 }
261 }
262 }
263 }
264 lua_pushboolean(L, 0);
265 return 1;
266}
267
268static int mysqllib_getmessage(lua_State * L)
269{
270 if (mysqllib_state.initialized) {
271 mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
272 if (data != NULL) {
273 lua_pushstring(L, mysqllib_state.mysql_error(data->db));
274 return 1;
275 }
276 }
277 return 0;
278}
279
280
281
282static int mysqllib_free(lua_State * L)
283{
284 return mysqllib_close(L);
285}
286
287
288
289static int mysqllib_tostring(lua_State * L)
290{
291 if (mysqllib_state.initialized) {
292 mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
293 if (data != NULL) {
294 (void) lua_pushfstring(L, "<mysqllib-instance %p>", data);
295 } else {
296 lua_pushnil(L);
297 }
298 return 1;
299 } else {
300 return 0;
301 }
302}
303
304static const struct luaL_Reg mysqllib_metatable[] = {
305 { "__tostring", mysqllib_tostring },
306 { "__gc", mysqllib_free },
307 { NULL, NULL },
308};
309
310static struct luaL_Reg mysqllib_function_list[] = {
311 { "initialize", mysqllib_initialize },
312 { "open", mysqllib_open },
313 { "close", mysqllib_close },
314 { "execute", mysqllib_execute },
315 { "getmessage", mysqllib_getmessage },
316 { NULL, NULL },
317};
318
319int luaopen_mysql(lua_State * L)
320{
321 luaL_newmetatable(L, MYSQLLIB_METATABLE);
322 luaL_setfuncs(L, mysqllib_metatable, 0);
323 lmt_library_register(L, "mysql", mysqllib_function_list);
324 return 0;
325}
326 |