#include "api.h" #include "buffer.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) { delete (mySQL*)ptr; } void input_error(void* caller) { api_runtime_error(caller, "bad arguments"); } #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); } static zsRegPrimitive my0("mysql", 0, sql_create); void init_embedded_mysql() { // Do nothing but to let the main program load the library to its thread. return; } #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); } static zsRegPrimitive my0("mysql", 0, sql_create); 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 my1("connect", MYSQL_TYPE, sql_connect); #endif 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()); } static zsRegPrimitive my2("version", MYSQL_TYPE, sql_version); 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); if (o->res) return api_create_integer(caller, mysql_num_rows(o->res)); return 0; } return api_create_string(caller, mysql_error(o->mysql)); } static zsRegPrimitive my3("query", MYSQL_TYPE, sql_query); 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); zsBuffer buf(2*n+2); mysql_real_escape_string(o->mysql, buf.u.pchar, s, n); return api_create_string(caller, buf.u.pchar); } void *ptr = api_get_ptr(caller, args[1]); int n = api_get_integer(caller, args[2]); zsBuffer buf(2*n+2); mysql_real_escape_string(o->mysql, buf.u.pchar, (const char*)ptr, n); return api_create_string(caller, buf.u.pchar); } static zsRegPrimitive my4("escape", MYSQL_TYPE, sql_escape); 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 ncol = mysql_num_fields(o->res); if (api_get_integer(caller, args[1]) != 0) { while (row) { for (int i = 0; i < ncol; i++) { if (i == ncol-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 (ncol > 1) { void *arr = api_create_array(caller, ncol); for (int i = 0; i < ncol; 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 (ncol == 1) { return api_create_string(caller, row[0] ? row[0] : "NULL"); } return 0; } static zsRegPrimitive my5("fetch", MYSQL_TYPE, sql_fetch); /* void* sql_mean(void *caller, int nargs, void** args) { if (nargs < 1) 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 nrow = mysql_num_rows(o->res); int ncol = mysql_num_fields(o->res); if (nrow <= 0 || ncol <= 0) return 0; zsBuffer buf(ncol*sizeof(double)); int j; for (j = 0; j < ncol; j++) buf.u.pdouble[j] = 0; while (row) { for (j = 0; j < ncol; j++) buf.u.pdouble[j] += atof(row[j]); row = mysql_fetch_row(o->res); } if (ncol > 1) { void *arr = api_create_array(caller, ncol); for (j = 0; j < ncol; j++) { api_set_array_object2(caller, arr, j, api_create_real(caller, buf.u.pdouble[j]/nrow)); } return arr; } return api_create_real(caller, buf.u.pdouble[0]/nrow); } static zsRegPrimitive my6("mean", MYSQL_TYPE, sql_mean); void* sql_stdev(void *caller, int nargs, void** args) { if (nargs < 1) 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 nrow = mysql_num_rows(o->res); int ncol = mysql_num_fields(o->res); if (nrow <= 0 || ncol <= 0) return 0; zsBuffer d1(ncol*sizeof(double)), d2(ncol*sizeof(double)); int j; for (j = 0; j < ncol; j++) { d1.u.pdouble[j] = 0; d2.u.pdouble[j] = 0; } while (row) { for (j = 0; j < ncol; j++) { double d = atof(row[j]); d1.u.pdouble[j] += d; d2.u.pdouble[j] += d*d; } row = mysql_fetch_row(o->res); } if (ncol > 1) { void *arr = api_create_array(caller, ncol); for (j = 0; j < ncol; j++) { double d = d2.u.pdouble[j]-d1.u.pdouble[j]*d1.u.pdouble[j]/nrow; if (nrow == 1) { api_set_array_object2(caller, arr, j, api_create_real(caller, 0)); } else { api_set_array_object2(caller, arr, j, api_create_real(caller, sqrt(d/(nrow-1)))); } } return arr; } if (nrow == 1) { return api_create_real(caller, 0); } else { double d = d2.u.pdouble[0]-d1.u.pdouble[0]*d1.u.pdouble[0]/nrow; return api_create_real(caller, sqrt(d/(nrow-1))); } } static zsRegPrimitive my7("stdev", MYSQL_TYPE, sql_stdev); */