#ifdef WITH_MYSQL #include "squirrel.h" #include "mysql.h" #include #include #include #include "sqstdblobimpl.h" SQ_OPT_STRING_STRLEN(); #include "dynamic_library.h" /*SquiLu local mysql_functions = [ ["MYSQL *", "mysql_init", "MYSQL *mysql"], ["MYSQL *", "mysql_real_connect", @"MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag"], ["void", "mysql_close", "MYSQL *sock"], ["const char *", "mysql_error", "MYSQL *mysql"], ["int", "mysql_ping", "MYSQL *mysql"], ["unsigned long", "mysql_real_escape_string", @"MYSQL *mysql, char *to,const char *from, unsigned long length"], ["unsigned long", "mysql_get_server_version", "MYSQL *mysql"], ["unsigned long", "mysql_insert_id", "MYSQL *mysql"], ["void", "mysql_data_seek", "MYSQL_RES *result, my_ulonglong offset"], ["MYSQL_RES *", "mysql_store_result", "MYSQL *mysql"], ["int", "mysql_real_query", @"MYSQL *mysql, const char *q, unsigned long length"], ["my_ulonglong", "mysql_num_rows", "MYSQL_RES *res"], ["my_ulonglong", "mysql_affected_rows", "MYSQL *mysql"], ["unsigned int", "mysql_num_fields", "MYSQL_RES *res"], ["MYSQL_FIELD *", "mysql_fetch_fields", "MYSQL_RES *res"], ["MYSQL_FIELD *", "mysql_fetch_field_direct", "MYSQL_RES *res, unsigned int fieldnr"], ["MYSQL_ROW", "mysql_fetch_row", "MYSQL_RES *res"], ["unsigned long *", "mysql_fetch_lengths", "MYSQL_RES *res"], ["void", "mysql_free_result", "MYSQL_RES *result"], ["my_bool", "mysql_eof", "MYSQL_RES *res"], //prepared statements ["MYSQL_STMT *", "mysql_stmt_init", "MYSQL *mysql"], ["int", "mysql_stmt_prepare", @"MYSQL_STMT *stmt, const char *query, unsigned long length"], ["int", "mysql_stmt_execute", "MYSQL_STMT *stmt"], ["unsigned long", "mysql_stmt_param_count", "MYSQL_STMT * stmt"], ["my_bool", "mysql_stmt_bind_param", "MYSQL_STMT * stmt, MYSQL_BIND * bnd"], ["my_bool", "mysql_stmt_reset", "MYSQL_STMT * stmt"], ["my_bool", "mysql_stmt_free_result", "MYSQL_STMT * stmt"], ["my_bool", "mysql_stmt_close", "MYSQL_STMT * stmt"], ["const char *", "mysql_stmt_error", "MYSQL_STMT * stmt"], ]; function write_mysql_functions_declaration(){ foreach(k,v in mysql_functions) { putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");"); putsnl("static " + v[1] + "_t dl" + v[1] + " = 0;"); } } function write_mysql_functions_load(){ foreach(k,v in mysql_functions){ putsnl("dl" + v[1] + " = (" + v[1] + "_t) libmysqlclient.dlsym(\"" + v[1] + "\");"); putsnl("if(!dl" + v[1] + ") return false;"); } } SquiLu*/ static DynamicLibrary libmysqlclient; //@write_mysql_functions_declaration(); // generated-code:begin typedef MYSQL * (*mysql_init_t)(MYSQL *mysql); static mysql_init_t dlmysql_init = 0; typedef MYSQL * (*mysql_real_connect_t)(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); static mysql_real_connect_t dlmysql_real_connect = 0; typedef void (*mysql_close_t)(MYSQL *sock); static mysql_close_t dlmysql_close = 0; typedef const char * (*mysql_error_t)(MYSQL *mysql); static mysql_error_t dlmysql_error = 0; typedef int (*mysql_ping_t)(MYSQL *mysql); static mysql_ping_t dlmysql_ping = 0; typedef unsigned long (*mysql_real_escape_string_t)(MYSQL *mysql, char *to,const char *from, unsigned long length); static mysql_real_escape_string_t dlmysql_real_escape_string = 0; typedef unsigned long (*mysql_get_server_version_t)(MYSQL *mysql); static mysql_get_server_version_t dlmysql_get_server_version = 0; typedef unsigned long (*mysql_insert_id_t)(MYSQL *mysql); static mysql_insert_id_t dlmysql_insert_id = 0; typedef void (*mysql_data_seek_t)(MYSQL_RES *result, my_ulonglong offset); static mysql_data_seek_t dlmysql_data_seek = 0; typedef MYSQL_RES * (*mysql_store_result_t)(MYSQL *mysql); static mysql_store_result_t dlmysql_store_result = 0; typedef int (*mysql_real_query_t)(MYSQL *mysql, const char *q, unsigned long length); static mysql_real_query_t dlmysql_real_query = 0; typedef my_ulonglong (*mysql_num_rows_t)(MYSQL_RES *res); static mysql_num_rows_t dlmysql_num_rows = 0; typedef my_ulonglong (*mysql_affected_rows_t)(MYSQL *mysql); static mysql_affected_rows_t dlmysql_affected_rows = 0; typedef unsigned int (*mysql_num_fields_t)(MYSQL_RES *res); static mysql_num_fields_t dlmysql_num_fields = 0; typedef MYSQL_FIELD * (*mysql_fetch_fields_t)(MYSQL_RES *res); static mysql_fetch_fields_t dlmysql_fetch_fields = 0; typedef MYSQL_FIELD * (*mysql_fetch_field_direct_t)(MYSQL_RES *res, unsigned int fieldnr); static mysql_fetch_field_direct_t dlmysql_fetch_field_direct = 0; typedef MYSQL_ROW (*mysql_fetch_row_t)(MYSQL_RES *res); static mysql_fetch_row_t dlmysql_fetch_row = 0; typedef unsigned long * (*mysql_fetch_lengths_t)(MYSQL_RES *res); static mysql_fetch_lengths_t dlmysql_fetch_lengths = 0; typedef void (*mysql_free_result_t)(MYSQL_RES *result); static mysql_free_result_t dlmysql_free_result = 0; typedef my_bool (*mysql_eof_t)(MYSQL_RES *res); static mysql_eof_t dlmysql_eof = 0; typedef MYSQL_STMT * (*mysql_stmt_init_t)(MYSQL *mysql); static mysql_stmt_init_t dlmysql_stmt_init = 0; typedef int (*mysql_stmt_prepare_t)(MYSQL_STMT *stmt, const char *query, unsigned long length); static mysql_stmt_prepare_t dlmysql_stmt_prepare = 0; typedef int (*mysql_stmt_execute_t)(MYSQL_STMT *stmt); static mysql_stmt_execute_t dlmysql_stmt_execute = 0; typedef unsigned long (*mysql_stmt_param_count_t)(MYSQL_STMT * stmt); static mysql_stmt_param_count_t dlmysql_stmt_param_count = 0; typedef my_bool (*mysql_stmt_bind_param_t)(MYSQL_STMT * stmt, MYSQL_BIND * bnd); static mysql_stmt_bind_param_t dlmysql_stmt_bind_param = 0; typedef my_bool (*mysql_stmt_reset_t)(MYSQL_STMT * stmt); static mysql_stmt_reset_t dlmysql_stmt_reset = 0; typedef my_bool (*mysql_stmt_free_result_t)(MYSQL_STMT * stmt); static mysql_stmt_free_result_t dlmysql_stmt_free_result = 0; typedef my_bool (*mysql_stmt_close_t)(MYSQL_STMT * stmt); static mysql_stmt_close_t dlmysql_stmt_close = 0; typedef const char * (*mysql_stmt_error_t)(MYSQL_STMT * stmt); static mysql_stmt_error_t dlmysql_stmt_error = 0; // generated-code:end static const char *dynamicLibName = DYNLIB_FOR_OS(libmysqlclient); static bool load_libmysqlclient() { if(dlmysql_init) return true; if(libmysqlclient.open(dynamicLibName)) { //@write_mysql_functions_load(); // generated-code:begin dlmysql_init = (mysql_init_t) libmysqlclient.dlsym("mysql_init"); if(!dlmysql_init) return false; dlmysql_real_connect = (mysql_real_connect_t) libmysqlclient.dlsym("mysql_real_connect"); if(!dlmysql_real_connect) return false; dlmysql_close = (mysql_close_t) libmysqlclient.dlsym("mysql_close"); if(!dlmysql_close) return false; dlmysql_error = (mysql_error_t) libmysqlclient.dlsym("mysql_error"); if(!dlmysql_error) return false; dlmysql_ping = (mysql_ping_t) libmysqlclient.dlsym("mysql_ping"); if(!dlmysql_ping) return false; dlmysql_real_escape_string = (mysql_real_escape_string_t) libmysqlclient.dlsym("mysql_real_escape_string"); if(!dlmysql_real_escape_string) return false; dlmysql_get_server_version = (mysql_get_server_version_t) libmysqlclient.dlsym("mysql_get_server_version"); if(!dlmysql_get_server_version) return false; dlmysql_insert_id = (mysql_insert_id_t) libmysqlclient.dlsym("mysql_insert_id"); if(!dlmysql_insert_id) return false; dlmysql_data_seek = (mysql_data_seek_t) libmysqlclient.dlsym("mysql_data_seek"); if(!dlmysql_data_seek) return false; dlmysql_store_result = (mysql_store_result_t) libmysqlclient.dlsym("mysql_store_result"); if(!dlmysql_store_result) return false; dlmysql_real_query = (mysql_real_query_t) libmysqlclient.dlsym("mysql_real_query"); if(!dlmysql_real_query) return false; dlmysql_num_rows = (mysql_num_rows_t) libmysqlclient.dlsym("mysql_num_rows"); if(!dlmysql_num_rows) return false; dlmysql_affected_rows = (mysql_affected_rows_t) libmysqlclient.dlsym("mysql_affected_rows"); if(!dlmysql_affected_rows) return false; dlmysql_num_fields = (mysql_num_fields_t) libmysqlclient.dlsym("mysql_num_fields"); if(!dlmysql_num_fields) return false; dlmysql_fetch_fields = (mysql_fetch_fields_t) libmysqlclient.dlsym("mysql_fetch_fields"); if(!dlmysql_fetch_fields) return false; dlmysql_fetch_field_direct = (mysql_fetch_field_direct_t) libmysqlclient.dlsym("mysql_fetch_field_direct"); if(!dlmysql_fetch_field_direct) return false; dlmysql_fetch_row = (mysql_fetch_row_t) libmysqlclient.dlsym("mysql_fetch_row"); if(!dlmysql_fetch_row) return false; dlmysql_fetch_lengths = (mysql_fetch_lengths_t) libmysqlclient.dlsym("mysql_fetch_lengths"); if(!dlmysql_fetch_lengths) return false; dlmysql_free_result = (mysql_free_result_t) libmysqlclient.dlsym("mysql_free_result"); if(!dlmysql_free_result) return false; dlmysql_eof = (mysql_eof_t) libmysqlclient.dlsym("mysql_eof"); if(!dlmysql_eof) return false; dlmysql_stmt_init = (mysql_stmt_init_t) libmysqlclient.dlsym("mysql_stmt_init"); if(!dlmysql_stmt_init) return false; dlmysql_stmt_prepare = (mysql_stmt_prepare_t) libmysqlclient.dlsym("mysql_stmt_prepare"); if(!dlmysql_stmt_prepare) return false; dlmysql_stmt_execute = (mysql_stmt_execute_t) libmysqlclient.dlsym("mysql_stmt_execute"); if(!dlmysql_stmt_execute) return false; dlmysql_stmt_param_count = (mysql_stmt_param_count_t) libmysqlclient.dlsym("mysql_stmt_param_count"); if(!dlmysql_stmt_param_count) return false; dlmysql_stmt_bind_param = (mysql_stmt_bind_param_t) libmysqlclient.dlsym("mysql_stmt_bind_param"); if(!dlmysql_stmt_bind_param) return false; dlmysql_stmt_reset = (mysql_stmt_reset_t) libmysqlclient.dlsym("mysql_stmt_reset"); if(!dlmysql_stmt_reset) return false; dlmysql_stmt_free_result = (mysql_stmt_free_result_t) libmysqlclient.dlsym("mysql_stmt_free_result"); if(!dlmysql_stmt_free_result) return false; dlmysql_stmt_close = (mysql_stmt_close_t) libmysqlclient.dlsym("mysql_stmt_close"); if(!dlmysql_stmt_close) return false; dlmysql_stmt_error = (mysql_stmt_error_t) libmysqlclient.dlsym("mysql_stmt_error"); if(!dlmysql_stmt_error) return false; // generated-code:end return true; } return false; } //////////////////////////////////////////////////////////////////////////////// static const SQChar *MySQL_TAG = _SC("MySQL"); static SQRESULT get_mysql_instance(HSQUIRRELVM v, SQInteger idx, MYSQL **self){ SQRESULT _rc_; if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)self,(void*)MySQL_TAG)) < 0) return _rc_; if(!*self) return sq_throwerror(v, _SC("database is closed")); return _rc_; } #define GET_mysql_INSTANCE_AT(idx) \ MYSQL *self=NULL; \ if((_rc_ = get_mysql_instance(v,idx,&self)) < 0) return _rc_; #define GET_mysql_INSTANCE() GET_mysql_INSTANCE_AT(1) static const SQChar *MySQL_Result_TAG = _SC("MySQL_Result"); static const SQChar *_curr_row_key = _SC("_curr_row"); static SQRESULT get_mysql_result_instance(HSQUIRRELVM v, SQInteger idx, MYSQL_RES **self){ SQRESULT _rc_; if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)self,(void*)MySQL_Result_TAG)) < 0) return _rc_; if(!*self) return sq_throwerror(v, _SC("MYSQL_RES is closed")); return _rc_; } #define GET_mysql_result_INSTANCE_AT(idx) \ MYSQL_RES *self=NULL; \ if((_rc_ = get_mysql_result_instance(v,idx,&self)) < 0) return _rc_; #define GET_mysql_result_INSTANCE() GET_mysql_result_INSTANCE_AT(1) static SQRESULT sq_mysql_result_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v) { MYSQL_RES *self = ((MYSQL_RES *)p); if (self) dlmysql_free_result(self); return 0; } static SQRESULT sq_mysql_result_close(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_result_INSTANCE(); dlmysql_free_result(self); sq_setinstanceup(v, 1, 0); //next calls will fail with "Pgresult is closed" return 0; } static SQRESULT sq_mysql_result_col_count(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_result_INSTANCE(); sq_pushinteger(v, (SQInteger)dlmysql_num_fields(self)); return 1; } static SQRESULT sq_mysql_result_row_count(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_result_INSTANCE(); sq_pushinteger(v, (SQInteger)dlmysql_num_rows(self)); return 1; } static SQRESULT sq_mysql_result_col_name(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_result_INSTANCE(); SQ_GET_INTEGER(v, 2, col); if(col < 0 || col > dlmysql_num_fields(self)-1) return sq_throwerror(v, _SC("invalid col number (%d)"), col); MYSQL_FIELD *fields = dlmysql_fetch_fields(self); sq_pushstring(v, fields[col].name, -1); return 1; } static int get_field_idx(MYSQL_RES *self, const SQChar *name){ MYSQL_FIELD *fields = dlmysql_fetch_fields(self); unsigned int count = dlmysql_num_fields(self); for(unsigned int i=0; i= row_count) return sq_throwerror(v, _SC("invalid row (%d)"), row); int col_count = dlmysql_num_fields(self); sq_newarray(v, col_count); dlmysql_data_seek(self, row); const MYSQL_ROW res_row = dlmysql_fetch_row(self); unsigned long *lengths = dlmysql_fetch_lengths(self); for(int i=0; i < col_count; ++i){ sq_pushinteger(v, i); sq_pushstring(v, (const SQChar*)res_row[i], lengths[i]); sq_rawset(v, -3); } return 1; } static SQRESULT sq_mysql_result_row_as_table(HSQUIRRELVM v){ SQ_FUNC_VARS(v); GET_mysql_result_INSTANCE(); SQ_OPT_INTEGER(v, 2, row, -1); if(row < 0){ sq_pushstring(v, _curr_row_key, -1); if(sq_get(v, 1) == SQ_OK){ sq_getinteger(v, -1, &row); } } int row_count = dlmysql_num_rows(self); if(row < 0 || row >= row_count) return sq_throwerror(v, _SC("invalid row (%d)"), row); int col_count = dlmysql_num_fields(self); sq_newtableex(v, col_count); dlmysql_data_seek(self, row); const MYSQL_ROW res_row = dlmysql_fetch_row(self); unsigned long *lengths = dlmysql_fetch_lengths(self); MYSQL_FIELD *fields = dlmysql_fetch_fields(self); for(int i=0; i < col_count; ++i){ sq_pushstring(v, fields[i].name, -1); sq_pushstring(v, (const SQChar*)res_row[i], lengths[i]); sq_rawset(v, -3); } return 1; } #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_mysql_result_##name,nparams,tycheck} static SQRegFunction sq_mysql_result_methods[] = { _DECL_FUNC(close, 1, _SC("x")), _DECL_FUNC(eof, 1, _SC("x")), _DECL_FUNC(next_row, 1, _SC("x")), _DECL_FUNC(col_count, 1, _SC("x")), _DECL_FUNC(row_count, 1, _SC("x")), _DECL_FUNC(col_name, 2, _SC("xi")), _DECL_FUNC(col_index, 2, _SC("xs")), _DECL_FUNC(col_value, 2, _SC("x i|s")), _DECL_FUNC(row_as_array, -1, _SC("xi")), _DECL_FUNC(row_as_table, -1, _SC("xi")), {0,0} }; #undef _DECL_FUNC static const SQChar *MySQL_Statement_TAG = _SC("MySQL_Statement"); static SQRESULT get_mysql_statement_instance(HSQUIRRELVM v, SQInteger idx, MYSQL_STMT **self){ SQRESULT _rc_; if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)self,(void*)MySQL_Statement_TAG)) < 0) return _rc_; if(!*self) return sq_throwerror(v, _SC("MySql statement is closed")); return _rc_; } #define GET_mysql_statement_INSTANCE_AT(idx) \ MYSQL_STMT *self=NULL; \ if((_rc_ = get_mysql_statement_instance(v,idx,&self)) < 0) return _rc_; #define GET_mysql_statement_INSTANCE() GET_mysql_statement_INSTANCE_AT(1) static SQRESULT sq_mysql_statement_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v) { MYSQL_STMT *self = ((MYSQL_STMT *)p); if (self) dlmysql_stmt_close(self); return 0; } static SQRESULT sq_mysql_statement_close(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_statement_INSTANCE(); sq_mysql_statement_releasehook(self, 0, v); sq_setinstanceup(v, 1, 0); //next calls will fail with "Pgstatement is closed" return 0; } class AllocMemory { unsigned int mem_size; public: unsigned char *mem; AllocMemory(unsigned int size){ mem_size = size; mem = (unsigned char *)sq_malloc(mem_size); } ~AllocMemory(){ if(mem) sq_free(mem, mem_size); } }; static SQRESULT sq_mysql_statement_bind(HSQUIRRELVM v){ SQ_FUNC_VARS(v); GET_mysql_statement_INSTANCE(); unsigned long expected_params = dlmysql_stmt_param_count(self); if(_top_ != expected_params){ return sq_throwerror(v, "Expect %d params but got %d !", expected_params, _top_); } unsigned int bind_memory_size = sizeof(MYSQL_BIND) * expected_params; AllocMemory bind_mem(bind_memory_size); AllocMemory buffer(expected_params * sizeof(double)); if (expected_params > 0) { if (bind_mem.mem == NULL || buffer.mem == NULL) { return sq_throwerror(v, "Could not alloc bind params"); } memset(bind_mem.mem, 0, bind_memory_size); } MYSQL_BIND *bind = (MYSQL_BIND*)bind_mem.mem; int offset = 0; for (int argn = 2; argn <= _top_; ++argn) { SQObjectType ptype = sq_gettype(v, argn); int i = argn - 2; const char *str = NULL; size_t *str_len = NULL; double *num = NULL; int *boolean_or_int = NULL; switch(ptype) { case OT_NULL:{ bind[i].buffer_type = MYSQL_TYPE_NULL; bind[i].is_null = (my_bool*)1; } break; case OT_BOOL:{ SQ_GET_BOOL(v, argn, param_bool); boolean_or_int = (int *)(buffer.mem + offset); offset += sizeof(int); *boolean_or_int = param_bool; bind[i].buffer_type = MYSQL_TYPE_LONG; bind[i].is_null = (my_bool*)0; bind[i].buffer = (char *)boolean_or_int; bind[i].length = 0; } break; case OT_INTEGER:{ SQ_GET_INTEGER(v, argn, param_int); boolean_or_int = (int *)(buffer.mem + offset); offset += sizeof(int); *boolean_or_int = param_int; bind[i].buffer_type = MYSQL_TYPE_LONG; bind[i].is_null = (my_bool*)0; bind[i].buffer = (char *)boolean_or_int; bind[i].length = 0; } break; case OT_FLOAT:{ /* * num needs to be it's own * memory here */ num = (double *)(buffer.mem + offset); offset += sizeof(double); SQ_GET_FLOAT(v, argn, param_float); *num = param_float; bind[i].buffer_type = MYSQL_TYPE_DOUBLE; bind[i].is_null = (my_bool*)0; bind[i].buffer = (char *)num; bind[i].length = 0; } break; case OT_STRING:{ unsigned long slength; /* output length pointer */ SQ_GET_STRING(v, argn, param_string); str_len = (size_t *)(buffer.mem + offset); offset += sizeof(size_t); str = param_string; bind[i].buffer_type = MYSQL_TYPE_STRING; bind[i].is_null = (my_bool*)0; bind[i].buffer = (char *)str; slength = *str_len; bind[i].length = &slength; } break; default:{ return sq_throwerror(v, "Unsupported bind parameter type %d", i); } } } sq_pushbool(v, dlmysql_stmt_bind_param(self, bind)); return 1; } static SQRESULT sq_mysql_statement_execute(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_statement_INSTANCE(); if (dlmysql_stmt_execute(self)) { return sq_throwerror(v, _SC("error executing prepared statement. MySQL: %s"), dlmysql_stmt_error(self)); } return 0; } #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_mysql_statement_##name,nparams,tycheck} static SQRegFunction sq_mysql_statement_methods[] = { _DECL_FUNC(close, 1, _SC("x")), _DECL_FUNC(bind, -2, _SC("x.")), _DECL_FUNC(execute, 1, _SC("x")), {0,0} }; #undef _DECL_FUNC static SQRESULT sq_mysql_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v) { MYSQL *self = ((MYSQL *)p); if (self) dlmysql_close(self); return 0; } static SQRESULT sq_mysql_constructor(HSQUIRRELVM v) { SQ_FUNC_VARS(v); SQ_GET_STRING(v, 2, host); SQ_GET_STRING(v, 3, username); SQ_GET_STRING(v, 4, password); SQ_GET_STRING(v, 5, sourcename); SQ_OPT_INTEGER(v, 6, port, 3306); SQ_OPT_STRING(v, 7, sockname, NULL); SQ_OPT_INTEGER(v, 8, optflags, 0); MYSQL *self=0; if(load_libmysqlclient()) { self = dlmysql_init(NULL); if (!self) return sq_throwerror(v, _SC("error connecting: Out of memory.")); if (!dlmysql_real_connect(self, host, username, password, sourcename, port, sockname, optflags)) { SQRESULT res = sq_throwerror(v, _SC("error connecting to database. MySQL: %s"), dlmysql_error(self)); dlmysql_close (self); /* Close conn if connect failed */ return res; } } else return sq_throwerror(v, _SC("Failed to load libmysqlclient !")); sq_setinstanceup(v, 1, self); sq_setreleasehook(v,1, sq_mysql_releasehook); //save a weakref to allow statement return it's db sq_pushuserpointer(v, self); sq_weakref(v, 1); sq_setonregistrytable(v); return 1; } static SQRESULT sq_mysql_close(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); dlmysql_close(self); sq_setinstanceup(v, 1, 0); //next calls will fail with "database is closed" return 0; } static SQRESULT sq_mysql_exec_dml(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); SQ_GET_STRING(v, 2, szSQL); if (dlmysql_real_query(self, szSQL, szSQL_size)) /* error executing query */ return sq_throwerror(v, _SC("error executing query. MySQL: %s"), dlmysql_error(self)); sq_pushinteger(v, (SQInteger)dlmysql_affected_rows(self)); return 1; } static SQRESULT sq_mysql_exec_scalar(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); SQ_GET_STRING(v, 2, szSQL); int result = 0; if (dlmysql_real_query(self, szSQL, szSQL_size)) /* error executing query */ return sq_throwerror(v, _SC("error executing query. MySQL: %s"), dlmysql_error(self)); MYSQL_RES *qres = dlmysql_store_result(self); bool is_ok = (dlmysql_num_rows(qres) == 1) && (dlmysql_num_fields(qres) > 0); if (is_ok) { MYSQL_ROW row = dlmysql_fetch_row(qres); unsigned long *lengths = dlmysql_fetch_lengths(qres); result = lengths[0] && row[0] ? atoi(row[0]) : 0; } dlmysql_free_result(qres); if (!is_ok) return sq_throwerror(v, _SC("invalid scalar query (%s)"), szSQL); sq_pushinteger(v, result); return 1; } static SQRESULT sq_mysql_exec_query(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); SQ_GET_STRING(v, 2, szSQL); if (dlmysql_real_query(self, szSQL, szSQL_size)) /* error executing query */ return sq_throwerror(v, _SC("error executing query. MySQL: %s"), dlmysql_error(self)); MYSQL_RES *qres = dlmysql_store_result(self); sq_pushroottable(v); sq_pushstring(v, MySQL_Result_TAG, -1); if(sq_get(v, -2) == SQ_OK){ if(sq_createinstance(v, -1) == SQ_OK){ sq_setinstanceup(v, -1, qres); sq_setreleasehook(v, -1, sq_mysql_result_releasehook); sq_pushstring(v, _curr_row_key, -1); sq_pushinteger(v, -1); sq_set(v, -3); return 1; } } return SQ_ERROR; } static SQRESULT sq_mysql_prepare(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); SQ_GET_STRING(v, 2, szSQL); MYSQL_STMT *stmt = dlmysql_stmt_init(self); if (!stmt) return sq_throwerror(v, _SC(" mysql_stmt_init(), out of memory\n")); if (dlmysql_stmt_prepare(stmt, szSQL, szSQL_size)) { SQRESULT res = sq_throwerror(v, dlmysql_stmt_error(stmt)); dlmysql_stmt_close(stmt); return res; } sq_pushroottable(v); sq_pushstring(v, MySQL_Statement_TAG, -1); if(sq_get(v, -2) == SQ_OK){ if(sq_createinstance(v, -1) == SQ_OK){ sq_setinstanceup(v, -1, stmt); sq_setreleasehook(v, -1, sq_mysql_statement_releasehook); return 1; } } return SQ_ERROR; } static SQRESULT sq_mysql_error_message(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); sq_pushstring(v, dlmysql_error(self), -1); return 1; } static SQRESULT sq_mysql_version(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); sq_pushinteger(v, (SQInteger)dlmysql_get_server_version(self)); return 1; } static SQRESULT sq_mysql_last_insert_id(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); sq_pushinteger(v, (SQInteger)dlmysql_insert_id(self)); return 1; } static SQRESULT sq_mysql_ping(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); sq_pushinteger(v, (SQInteger)dlmysql_ping(self)); return 1; } static SQRESULT sq_mysql_escape_string(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_mysql_INSTANCE(); SQ_GET_STRING(v, 2, str); SQInteger to_size = (str_size*2+1) * sizeof(SQChar); SQChar *to = sq_getscratchpad(v, to_size); if(to) { SQInteger new_size = (SQInteger)dlmysql_real_escape_string(self, to, str, str_size); sq_pushstring(v, to, new_size); return 1; } return sq_throwerror(v, _SC("could not allocate escaped string")); } #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_mysql_##name,nparams,tycheck} static SQRegFunction sq_mysql_methods[] = { _DECL_FUNC(constructor, -5, _SC("xssssisi")), _DECL_FUNC(close, 1, _SC("x")), _DECL_FUNC(ping, 1, _SC("x")), _DECL_FUNC(exec_dml, 2, _SC("xs")), _DECL_FUNC(exec_scalar, 2, _SC("xs")), _DECL_FUNC(exec_query, 2, _SC("xs")), _DECL_FUNC(prepare, 2, _SC("xs")), _DECL_FUNC(error_message, 1, _SC("x")), _DECL_FUNC(version, 1, _SC("x")), _DECL_FUNC(last_insert_id, 1, _SC("x")), _DECL_FUNC(escape_string, 2, _SC("xs")), {0,0} }; #undef _DECL_FUNC #ifdef __cplusplus extern "C" { #endif SQRESULT sqext_register_MySQL(HSQUIRRELVM v) { sq_pushstring(v,MySQL_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(void*)MySQL_TAG); sq_insert_reg_funcs(v, sq_mysql_methods); sq_newslot(v,-3,SQTrue); sq_pushstring(v,MySQL_Statement_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(void*)MySQL_Statement_TAG); sq_insert_reg_funcs(v, sq_mysql_statement_methods); sq_newslot(v,-3,SQTrue); sq_pushstring(v,MySQL_Result_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(void*)MySQL_Result_TAG); sq_insert_reg_funcs(v, sq_mysql_result_methods); sq_pushstring(v, _curr_row_key, -1); sq_pushnull(v); sq_newslot(v, -3, SQFalse); sq_newslot(v,-3,SQTrue); return 0; } #ifdef __cplusplus } #endif #endif