summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt3
-rw-r--r--doc/script_commands.txt4
-rw-r--r--src/common/mmo.h5
-rw-r--r--src/map/script.c122
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);