diff options
-rw-r--r-- | Changelog-Trunk.txt | 3 | ||||
-rw-r--r-- | doc/script_commands.txt | 4 | ||||
-rw-r--r-- | src/common/mmo.h | 5 | ||||
-rw-r--r-- | src/map/script.c | 122 |
4 files changed, 85 insertions, 49 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 6540641a4..1062d1481 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,9 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2007/09/22 + * Added a sanity check for MAX_ZENY (doesn't compile if too big). + * Redid the buildin_query_sql function. (fixes bugreport:81). [FlavioJS] 2007/09/21 * itemdb.c/h using a static array of 32k struct item_data* entries (faster itemdb loockup and a first step to remove map_session_data->inventory_data). diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 5acb3e883..c236adbb7 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5871,9 +5871,9 @@ set @i, distance(100,200,101,202); --------------------------------------- -*query_sql "your MySQL query", <array name>{,<array name>{; +*query_sql "your MySQL query", <array variable> {,<array variable>, ...}; -Returns up to 127 values into array and return the number of row +Puts up to 128 rows of values into the arrays and returns the number of rows. Example: set @nb, query_sql("select name,fame from `char` ORDER BY fame DESC LIMIT 5", @name$, @fame); diff --git a/src/common/mmo.h b/src/common/mmo.h index 619c75295..8e757d81a 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -497,4 +497,9 @@ enum { JOB_SOUL_LINKER, }; +// sanity checks... +#if MAX_ZENY > INT_MAX +#error MAX_ZENY is too big +#endif + #endif /* _MMO_H_ */ diff --git a/src/map/script.c b/src/map/script.c index 0a5b5fbc0..5dff55cac 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -12113,73 +12113,101 @@ BUILDIN_FUNC(setd) BUILDIN_FUNC(query_sql) { #ifndef TXT_ONLY - int i, j, nb_rows; - struct { char* dst_var_name; char type; } row[32]; - TBL_PC* sd = (st->rid) ? script_rid2sd(st) : NULL; + int i, j; + TBL_PC* sd = NULL; + const char* query; + struct script_data* data; + char* name; + int max_rows = 128;// maximum number of rows + int num_vars; + int num_cols; - const char* query = script_getstr(st,2); - if (SQL_ERROR == Sql_Query(mmysql_handle, query) ) + // check target variables + for( i = 3; script_hasdata(st,i); ++i ) + { + data = script_getdata(st, i); + if( data_isreference(data) && reference_tovariable(data) ) + {// it's a variable + name = reference_getname(data); + if( not_server_variable(*name) && sd == NULL ) + {// requires a player + sd = script_rid2sd(st); + if( sd == NULL ) + {// no player attached + script_reportdata(data); + st->state = END; + return 1; + } + } + if( not_array_variable(*name) ) + max_rows = 1;// not an array, limit to one row + } + else + { + ShowError("script:query_sql: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1; + } + } + num_vars = i - 3; + + // Execute the query + query = script_getstr(st,2); + if( SQL_ERROR == Sql_Query(mmysql_handle, query) ) { Sql_ShowDebug(mmysql_handle); script_pushint(st, 0); return 1; } - // Count the number of rows to store - nb_rows = Sql_NumColumns(mmysql_handle); - //FIXME: what sick mind would write something like this? - - // Can't store more row than variable - if (nb_rows > st->end - (st->start+3)) - nb_rows = st->end - (st->start+3); - - if (!nb_rows) - { - script_pushint(st,0); - return 0; // Nothing to store + if( Sql_NumRows(mmysql_handle) == 0 ) + {// No data received + Sql_FreeResult(mmysql_handle); + script_pushint(st, 0); + return 0; } - if (nb_rows > 32) + // Count the number of columns to store + num_cols = Sql_NumColumns(mmysql_handle); + if( num_vars < num_cols ) { - ShowWarning("buildin_query_sql: too many rows!\n"); - script_pushint(st,0); - return 1; + ShowWarning("script:query_sql: Too many columns, discarting last %u columns.\n", (unsigned int)(num_cols-num_vars)); + script_reportsrc(st); } - - memset(row, 0, sizeof(row)); - // Verify argument types - for(j=0; j < nb_rows; j++) + else if( num_vars > num_cols ) { - if(!data_isreference(script_getdata(st, 3+j))){ - ShowWarning("buildin_query_sql: Parameter %d is not a variable!\n", j); - script_pushint(st,0); - return 0; - } else { - // Store type of variable (string = 0/int = 1) - int num = st->stack->stack_data[st->start+3+j].u.num; - char* name = str_buf + str_data[num&0x00ffffff].str; - if(name[strlen(name)-1] != '$') { - row[j].type = 1; - } - row[j].dst_var_name = name; - } + ShowWarning("script:query_sql: Too many variables (%u extra).\n", (unsigned int)(num_vars-num_cols)); + script_reportsrc(st); } + // Store data - for (i = 0; i < 128 && SQL_SUCCESS == Sql_NextRow(mmysql_handle); i++) + for( i = 0; i < max_rows && SQL_SUCCESS == Sql_NextRow(mmysql_handle); ++i ) { - char* data; - Sql_GetData(mmysql_handle, j, &data, NULL); - for(j = 0; j < nb_rows; j++) { - if (row[j].type == 1) - setd_sub(st,sd, row[j].dst_var_name, i, (void *)atoi(data), script_getref(st,3+j)); + for( j = 0; j < num_vars; ++j ) + { + char* str = NULL; + + if( j < num_cols ) + Sql_GetData(mmysql_handle, j, &str, NULL); + + data = script_getdata(st, j+3); + name = reference_getname(data); + if( is_string_variable(name) ) + setd_sub(st, sd, name, i, (void *)(str?str:""), reference_getref(data)); else - setd_sub(st,sd, row[j].dst_var_name, i, (void *)data, script_getref(st,3+j)); + setd_sub(st, sd, name, i, (void *)(str?atoi(str):0), reference_getref(data)); } } + if( i == max_rows && max_rows < Sql_NumRows(mmysql_handle) ) + { + ShowWarning("script:query_sql: Only %d/%u rows have been stored.\n", max_rows, (unsigned int)Sql_NumRows(mmysql_handle)); + script_reportsrc(st); + } + // Free data Sql_FreeResult(mmysql_handle); - - script_pushint(st,i); + script_pushint(st, i); #else //for TXT version, we always return -1 script_pushint(st,-1); |