#include "api.h" #include "my_global.h" #include "mysql.h" #include #include #define MYSQL_TYPE 'MY' #pragma warning(disable: 4244) class zsRegPrimitive { public: zsRegPrimitive(const char* name, int type, void* func) { api_add_primitive(name, type, func); } }; class mySQL { public: mySQL() : res(0), mysql(0) { } ~mySQL() { if (mysql) mysql_close(mysql); if(res) mysql_free_result(res); } MYSQL *mysql; MYSQL_RES *res; }; void sql_destroy(void* ptr) { mySQL *o = (mySQL*)ptr; delete o; } void input_error(void* caller) { api_runtime_error(caller, "bad arguments"); } void* sql_version(void *caller, int nargs, void** args) { if (nargs < 1) input_error(caller); mySQL *o = (mySQL*)api_get_user(caller, args[0], MYSQL_TYPE); return api_create_string(caller, mysql_get_client_info()); } void* sql_query(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); mySQL *o = (mySQL*)api_get_user(caller, args[0], MYSQL_TYPE); if (o->res) { mysql_free_result(o->res); o->res = 0; } if (mysql_query(o->mysql, api_get_string(caller, args[1])) == 0) { o->res = mysql_store_result(o->mysql); return 0; } return api_create_string(caller, mysql_error(o->mysql)); } void* sql_escape(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); mySQL *o = (mySQL*)api_get_user(caller, args[0], MYSQL_TYPE); if (nargs == 2) { const char *s = api_get_string(caller, args[1]); int n = strlen(s); char *buf = new char[2*n + 2]; mysql_real_escape_string(o->mysql, buf, s, n); void *ret = api_create_string(caller, buf); delete[] buf; return ret; } void *ptr = api_get_ptr(caller, args[1]); int n = api_get_integer(caller, args[2]); char *buf = new char[2*n + 2]; mysql_real_escape_string(o->mysql, buf, (const char*)ptr, n); void *ret = api_create_string(caller, buf); delete[] buf; return ret; } void* sql_fetch(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); mySQL *o = (mySQL*)api_get_user(caller, args[0], MYSQL_TYPE); if (!o->res) return 0; MYSQL_ROW row = mysql_fetch_row(o->res); if (!row) return 0; int n = mysql_num_fields(o->res); if (api_get_integer(caller, args[1]) != 0) { while (row) { for (int i = 0; i < n; i++) { if (i == n-1) fprintf(stdout, "%s\n", row[i] ? row[i] : "NULL"); else fprintf(stdout, "%s, ", row[i] ? row[i] : "NULL"); } row = mysql_fetch_row(o->res); } return 0; } if (n > 1) { void *arr = api_create_array(caller, n); for (int i = 0; i < n; i++) { api_set_array_object2(caller, arr, i, row[i] ? api_create_string(caller, row[i]) : api_create_string(caller, "NULL")); } return arr; } else if (n == 1) { return api_create_string(caller, row[0] ? row[0] : "NULL"); } return 0; } #ifdef EMBEDDED_LIBRARY #include "myemb.h" void* sql_create(void *caller, int nargs, void** args) { mySQL *o = new mySQL; char *server_groups[] = { "client", "server", 0 }; char *server_options[2]; char opt1[] = "mysql_embedded", opt2[256]; server_options[0] = opt1; server_options[1] = opt2; strcpy(opt2, "--defaults-file="); if (nargs > 0) { strcat(opt2, api_get_string(caller, args[0])); } else { char buf[200]; GetCurrentDirectory(200, buf); strcat(opt2, buf); strcat(opt2, "\\my.ini"); } mysql_server_init(2, server_options, server_groups); o->mysql = mysql_init(NULL); if (!o->mysql) api_runtime_error(caller, "failed to initialize MySQL client"); if (mysql_options(o->mysql, MYSQL_READ_DEFAULT_GROUP, "client") != 0 || mysql_options(o->mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL) != 0 || mysql_real_connect(o->mysql, 0, 0, 0, 0, 0, 0, 0) == 0) api_runtime_error(caller, mysql_error(o->mysql)); return api_create_user(caller, o, 0, sql_destroy, MYSQL_TYPE); } void init_embedded_mysql() { static init_status = 0; if (init_status == 0) { zsRegPrimitive my0("mysql", 0, sql_create), my3("query", MYSQL_TYPE, sql_query), my4("escape", MYSQL_TYPE, sql_escape), my5("fetch", MYSQL_TYPE, sql_fetch); init_status = 1; } } #else void* sql_create(void *caller, int nargs, void** args) { mySQL *o = new mySQL; o->mysql = mysql_init(0); if (!o->mysql) api_runtime_error(caller, "failed to initialize MySQL client"); return api_create_user(caller, o, 0, sql_destroy, MYSQL_TYPE); } void* sql_connect(void *caller, int nargs, void** args) { if (nargs < 4) input_error(caller); mySQL *o = (mySQL*)api_get_user(caller, args[0], MYSQL_TYPE); const char *dbname = 0; if (nargs > 4) dbname = api_get_string(caller, args[4]); if (!mysql_real_connect( o->mysql, api_get_string(caller, args[1]), // host api_get_string(caller, args[2]), // user api_get_string(caller, args[3]), // password dbname, 0, 0, 0)) { return api_create_string(caller, mysql_error(o->mysql)); } return 0; } static zsRegPrimitive my0("mysql", 0, sql_create); static zsRegPrimitive my2("connect", MYSQL_TYPE, sql_connect); static zsRegPrimitive my3("query", MYSQL_TYPE, sql_query); static zsRegPrimitive my4("escape", MYSQL_TYPE, sql_escape); static zsRegPrimitive my5("fetch", MYSQL_TYPE, sql_fetch); #endif