two phase fix. first update your database by running the sql here:
Code:
--
--
-- this adds the new column that allows us to optimize the "find the recipe" algorithm
--
--
alter table tradeskill_recipe add column component_sum int( 16 );
--
--
-- create temporary data for backfilling the new column
--
--
create temporary table recipe_result ( select recipe_id, sum( item_id * componentcount ) as theSum from tradeskill_recipe_entries where componentcount > 0 group by recipe_id order by theSum );
--
--
-- this populates the new column with the derived data from the "entries" table
--
--
update tradeskill_recipe set component_sum = ( select theSum from recipe_result where recipe_result.recipe_id = tradeskill_recipe.id );
then patch the first GetTradeRecipe() method with this:
Code:
bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint8 tradeskill,
DBTradeskillRecipe_Struct *spec)
{
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES *result;
MYSQL_ROW row;
char *query = 0;
char where[ 10 ][ 16 ];
char buf2[ 1024 ];
char crcStr[ 32 ];
int buf3[10];
uint32 crc = 0;
uint32 sum = 0;
uint32 count = 0;
uint32 qcount = 0;
uint32 qlen = 0;
uint32 theRecipe = 0;
//use the world item type as type if we have a world item
//otherwise use the item's ID... this make the assumption that
//no tradeskill containers will have an item ID which is
//below the highest ID of objects, which is currently 0x30
uint32 type = c_type;
//dunno why I have to cast this up to call GetItem
const Item_Struct *istruct = ((const ItemInst *) container)->GetItem();
if(c_type == 0 && istruct) {
type = istruct->ID;
}
uint8 i;
for (i=0; i<10; i++) {
const ItemInst* inst = container->GetItem(i);
if (inst) {
const Item_Struct* item = GetItem(inst->GetItem()->ID);
if (item) {
buf3[ count ++ ] = item->ID;
crc += item->ID;
}
}
}
if(count < 1) {
return(false); //no items == no recipe
}
sprintf( buf2, "%s", "select tre.recipe_id from"
" tradeskill_recipe_entries tre, tradeskill_recipe where tre.item_id in ( " );
for( i = 0; i < count; i ++ )
{
if( i != 0 )
{
sprintf( where[ i ], ", %d", buf3[ i ] );
}
else
{
sprintf( where[ i ], "%d", buf3[ i ] );
}
strcat( buf2, where[ i ] );
}
strcat( buf2, " ) and componentcount > 0 and tradeskill_recipe.id = tre.recipe_id"
" and tradeskill_recipe.component_sum = " );
sprintf( crcStr, "%d group by recipe_id", crc );
strcat( buf2, crcStr );
qlen = MakeAnyLenString(&query, buf2 );
LogFile->write(EQEMuLog::Error, "Executing query: %s", query);
if (!RunQuery(query, qlen, errbuf, &result)) {
LogFile->write(EQEMuLog::Error, "Error in GetTradeRecept search, query: %s", query);
safe_delete_array(query);
LogFile->write(EQEMuLog::Error, "Error in GetTradeRecept search, error: %s", errbuf);
return(false);
}
safe_delete_array(query);
qcount = mysql_num_rows(result);
if( qcount != 1 )
{
if( qcount > 1 )
{
LogFile->write(EQEMuLog::Error, "Combine error: Recipe is not unique!");
}
//else, just not found i guess..
return(false);
}
else
{
row = mysql_fetch_row(result);
theRecipe = atoi( row[ 0 ] );
}
mysql_free_result(result);
return(GetTradeRecipe(theRecipe, c_type, tradeskill, spec));
}