summaryrefslogtreecommitdiff
path: root/source/luametatex/source/luaoptional/lmtmysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/luaoptional/lmtmysql.c')
-rw-r--r--source/luametatex/source/luaoptional/lmtmysql.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/source/luametatex/source/luaoptional/lmtmysql.c b/source/luametatex/source/luaoptional/lmtmysql.c
new file mode 100644
index 000000000..8509df7aa
--- /dev/null
+++ b/source/luametatex/source/luaoptional/lmtmysql.c
@@ -0,0 +1,325 @@
+/*
+ See license.txt in the root of this project.
+*/
+
+# include "luametatex.h"
+# include "lmtoptional.h"
+
+typedef void mysql_instance;
+typedef void mysql_result;
+typedef char **mysql_row;
+typedef unsigned int mysql_offset;
+
+typedef struct mysql_field {
+ char *name;
+ char *org_name;
+ char *table;
+ char *org_table;
+ char *db;
+ char *catalog;
+ char *def;
+ unsigned long length;
+ unsigned long max_length;
+ unsigned int name_length;
+ unsigned int org_name_length;
+ unsigned int table_length;
+ unsigned int org_table_length;
+ unsigned int db_length;
+ unsigned int catalog_length;
+ unsigned int def_length;
+ unsigned int flags;
+ unsigned int decimals;
+ unsigned int charsetnr;
+ int type;
+ void *extension;
+} mysql_field;
+
+# define MYSQLLIB_METATABLE "luatex.mysqllib"
+
+typedef struct mysqllib_data {
+ /*tex There is not much more than a pointer currently. */
+ mysql_instance * db;
+} mysqllib_data ;
+
+typedef struct mysqllib_state_info {
+
+ int initialized;
+ int padding;
+
+ mysql_instance * (*mysql_init) (
+ mysql_instance *mysql
+ );
+
+ mysql_instance * (*mysql_real_connect) (
+ mysql_instance *mysql,
+ const char *host,
+ const char *user,
+ const char *passwd,
+ const char *db,
+ unsigned int port,
+ const char *unix_socket,
+ unsigned long clientflag
+ );
+
+ unsigned int (*mysql_errno) (
+ mysql_instance *mysql
+ );
+
+ const char * (*mysql_error) (
+ mysql_instance *mysql
+ );
+
+ int (*mysql_real_query) (
+ mysql_instance *mysql,
+ const char *q,
+ unsigned long length
+ );
+
+ mysql_result * (*mysql_store_result) (
+ mysql_instance *mysql
+ );
+
+ void (*mysql_free_result) (
+ mysql_result *result
+ );
+
+ unsigned long long (*mysql_num_rows) (
+ mysql_result *res
+ );
+
+ mysql_row (*mysql_fetch_row) (
+ mysql_result *result
+ );
+
+ unsigned int (*mysql_affected_rows) (
+ mysql_instance *mysql
+ );
+
+ unsigned int (*mysql_field_count) (
+ mysql_instance *mysql
+ );
+
+ unsigned int (*mysql_num_fields) (
+ mysql_result *res
+ );
+
+ mysql_field * (*mysql_fetch_fields) (
+ mysql_result *res
+ );
+
+ mysql_offset (*mysql_field_seek) (
+ mysql_result *result,
+ mysql_offset offset
+ );
+
+ void (*mysql_close) (
+ mysql_instance *sock
+ );
+
+} mysqllib_state_info;
+
+static mysqllib_state_info mysqllib_state = {
+
+ .initialized = 0,
+ .padding = 0,
+
+ .mysql_init = NULL,
+ .mysql_real_connect = NULL,
+ .mysql_errno = NULL,
+ .mysql_error = NULL,
+ .mysql_real_query = NULL,
+ .mysql_store_result = NULL,
+ .mysql_free_result = NULL,
+ .mysql_num_rows = NULL,
+ .mysql_fetch_row = NULL,
+ .mysql_affected_rows = NULL,
+ .mysql_field_count = NULL,
+ .mysql_num_fields = NULL,
+ .mysql_fetch_fields = NULL,
+ .mysql_field_seek = NULL,
+ .mysql_close = NULL,
+
+};
+
+static int mysqllib_initialize(lua_State * L)
+{
+ if (! mysqllib_state.initialized) {
+ const char *filename = lua_tostring(L, 1);
+ if (filename != NULL) {
+
+ lmt_library lib = lmt_library_load(filename);
+
+ mysqllib_state.mysql_init = lmt_library_find(lib, "mysql_init" );
+ mysqllib_state.mysql_real_connect = lmt_library_find(lib, "mysql_real_connect" );
+ mysqllib_state.mysql_errno = lmt_library_find(lib, "mysql_errno" );
+ mysqllib_state.mysql_error = lmt_library_find(lib, "mysql_error" );
+ mysqllib_state.mysql_real_query = lmt_library_find(lib, "mysql_real_query" );
+ mysqllib_state.mysql_store_result = lmt_library_find(lib, "mysql_store_result" );
+ mysqllib_state.mysql_free_result = lmt_library_find(lib, "mysql_free_result" );
+ mysqllib_state.mysql_num_rows = lmt_library_find(lib, "mysql_num_rows" );
+ mysqllib_state.mysql_fetch_row = lmt_library_find(lib, "mysql_fetch_row" );
+ mysqllib_state.mysql_affected_rows = lmt_library_find(lib, "mysql_affected_rows" );
+ mysqllib_state.mysql_field_count = lmt_library_find(lib, "mysql_field_count" );
+ mysqllib_state.mysql_num_fields = lmt_library_find(lib, "mysql_num_fields" );
+ mysqllib_state.mysql_fetch_fields = lmt_library_find(lib, "mysql_fetch_fields" );
+ mysqllib_state.mysql_field_seek = lmt_library_find(lib, "mysql_field_seek" );
+ mysqllib_state.mysql_close = lmt_library_find(lib, "mysql_close" );
+
+ mysqllib_state.initialized = lmt_library_okay(lib);
+ }
+ }
+ lua_pushboolean(L, mysqllib_state.initialized);
+ return 1;
+}
+
+static int mysqllib_open(lua_State * L)
+{
+ if (mysqllib_state.initialized) {
+ const char * database = luaL_checkstring(L, 1);
+ const char * username = luaL_optstring(L, 2, NULL);
+ const char * password = luaL_optstring(L, 3, NULL);
+ const char * host = luaL_optstring(L, 4, NULL);
+ int port = lmt_optinteger(L, 5, 0);
+ const char * socket = NULL; /* luaL_optstring(L, 6, NULL); */
+ int flag = 0; /* luaL_optinteger(L, 7, 0); */
+ mysql_instance * db = mysqllib_state.mysql_init(NULL);
+ if (db != NULL) {
+ if (mysqllib_state.mysql_real_connect(db, host, username, password, database, port, socket, flag)) {
+ mysqllib_data *data = lua_newuserdatauv(L, sizeof(data), 0);
+ data->db = db ;
+ luaL_getmetatable(L, MYSQLLIB_METATABLE);
+ lua_setmetatable(L, -2);
+ return 1;
+ } else {
+ mysqllib_state.mysql_close(db);
+ }
+ }
+ }
+ return 0;
+}
+
+static int mysqllib_close(lua_State * L)
+{
+ if (mysqllib_state.initialized) {
+ mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
+ if (data != NULL) {
+ mysqllib_state.mysql_close(data->db);
+ data->db = NULL;
+ }
+ }
+ return 0;
+}
+
+/* execute(database,querystring,callback) : callback(nofcolumns,values,fields) */
+
+static int mysqllib_execute(lua_State * L)
+{
+ if (mysqllib_state.initialized) {
+ mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
+ if (data != NULL) {
+ size_t length = 0;
+ const char *query = lua_tolstring(L, 2, &length);
+ if (query != NULL) {
+ int error = mysqllib_state.mysql_real_query(data->db, query, (int) length);
+ if (!error) {
+ mysql_result * result = mysqllib_state.mysql_store_result(data->db);
+ if (result != NULL) {
+ int nofrows = 0;
+ int nofcolumns = 0;
+ mysqllib_state.mysql_field_seek(result, 0);
+ nofrows = (int) mysqllib_state.mysql_num_rows(result);
+ nofcolumns = mysqllib_state.mysql_num_fields(result);
+ /* This is similar to sqlite but there the callback is more indirect. */
+ if (nofcolumns > 0 && nofrows > 0) {
+ for (int r = 0; r < nofrows; r++) {
+ mysql_row row = mysqllib_state.mysql_fetch_row(result);
+ lua_pushvalue(L, -1);
+ lua_pushinteger(L, nofcolumns);
+ lua_createtable(L, nofcolumns, 0);
+ for (int c = 0; c < nofcolumns; c++) {
+ lua_pushstring(L, row[c]);
+ lua_rawseti(L, -2, (lua_Integer)c + 1);
+ }
+ if (r) {
+ lua_call(L, 2, 0);
+ } else {
+ mysql_field * fields = mysqllib_state.mysql_fetch_fields(result);
+ lua_createtable(L, nofcolumns, 0);
+ for (int c = 0; c < nofcolumns; c++) {
+ lua_pushstring(L, fields[c].name);
+ lua_rawseti(L, -2, (lua_Integer)c + 1);
+ }
+ lua_call(L, 3, 0);
+ }
+ }
+ }
+ mysqllib_state.mysql_free_result(result);
+ }
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ }
+ }
+ }
+ lua_pushboolean(L, 0);
+ return 1;
+}
+
+static int mysqllib_getmessage(lua_State * L)
+{
+ if (mysqllib_state.initialized) {
+ mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
+ if (data != NULL) {
+ lua_pushstring(L, mysqllib_state.mysql_error(data->db));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* private */
+
+static int mysqllib_free(lua_State * L)
+{
+ return mysqllib_close(L);
+}
+
+/* <string> = tostring(instance) */
+
+static int mysqllib_tostring(lua_State * L)
+{
+ if (mysqllib_state.initialized) {
+ mysqllib_data * data = luaL_checkudata(L, 1, MYSQLLIB_METATABLE);
+ if (data != NULL) {
+ (void) lua_pushfstring(L, "<mysqllib-instance %p>", data);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static const struct luaL_Reg mysqllib_metatable[] = {
+ { "__tostring", mysqllib_tostring },
+ { "__gc", mysqllib_free },
+ { NULL, NULL },
+};
+
+static struct luaL_Reg mysqllib_function_list[] = {
+ { "initialize", mysqllib_initialize },
+ { "open", mysqllib_open },
+ { "close", mysqllib_close },
+ { "execute", mysqllib_execute },
+ { "getmessage", mysqllib_getmessage },
+ { NULL, NULL },
+};
+
+int luaopen_mysql(lua_State * L)
+{
+ luaL_newmetatable(L, MYSQLLIB_METATABLE);
+ luaL_setfuncs(L, mysqllib_metatable, 0);
+ lmt_library_register(L, "mysql", mysqllib_function_list);
+ return 0;
+}