| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856 |
- #ifdef WITH_MYSQL
- #include "squirrel.h"
- #include "mysql.h"
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #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<count; ++i){
- if(scstrcmp(name, fields[i].name) == 0){
- return i;
- }
- }
- return -1;
- }
- static SQRESULT sq_mysql_result_col_index(HSQUIRRELVM v){
- SQ_FUNC_VARS_NO_TOP(v);
- GET_mysql_result_INSTANCE();
- SQ_GET_STRING(v, 2, name);
- sq_pushinteger(v, get_field_idx(self, name));
- return 1;
- }
- static SQRESULT sq_mysql_result_eof(HSQUIRRELVM v){
- SQ_FUNC_VARS_NO_TOP(v);
- GET_mysql_result_INSTANCE();
- sq_pushstring(v, _curr_row_key, -1);
- if(sq_get(v, 1) == SQ_OK){
- SQ_GET_INTEGER(v, -1, curr_row);
- sq_pushbool(v, curr_row < dlmysql_num_rows(self));
- }
- else sq_pushbool(v, SQTrue);
- return 1;
- }
- static SQRESULT sq_mysql_result_next_row(HSQUIRRELVM v){
- SQ_FUNC_VARS_NO_TOP(v);
- GET_mysql_result_INSTANCE();
- sq_pushstring(v, _curr_row_key, -1);
- sq_push(v, -1); //make a copy
- if(sq_get(v, 1) == SQ_OK){
- SQ_GET_INTEGER(v, -1, curr_row);
- if(++curr_row < dlmysql_num_rows(self)){
- sq_poptop(v);
- sq_pushinteger(v, curr_row);
- sq_set(v, 1);
- sq_pushbool(v, SQTrue);
- return 1;
- }
- }
- sq_pushbool(v, SQFalse);
- return 1;
- }
- static SQRESULT sq_mysql_result_col_value(HSQUIRRELVM v){
- SQ_FUNC_VARS_NO_TOP(v);
- GET_mysql_result_INSTANCE();
- SQObjectType ptype = sq_gettype(v, 2);
- int col = -1;
- if(ptype == OT_STRING){
- SQ_GET_STRING(v, 2, col_name);
- col = get_field_idx(self, col_name);
- }
- else
- {
- SQ_GET_INTEGER(v, 2, idx);
- col = idx;
- }
- if(col < 0) return sq_throwerror(v, _SC("invalid col index/name"));
- sq_pushstring(v, _curr_row_key, -1);
- if(sq_get(v, 1) == SQ_OK){
- SQ_GET_INTEGER(v, -1, curr_row);
- if(curr_row < dlmysql_num_rows(self)){
- dlmysql_data_seek(self, curr_row);
- const MYSQL_ROW res_row = dlmysql_fetch_row(self);
- unsigned long *lengths = dlmysql_fetch_lengths(self);
- sq_pushstring(v, (const SQChar*)res_row[col], lengths[col]);
- return 1;
- }
- }
- return SQ_ERROR;
- }
- static SQRESULT sq_mysql_result_row_as_array(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_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
|