[Tutorial] Using BlueG's MySQL plugin R7 (with cache)

Is there a logical way with threaded queries to perform multiple select queries in a single callback or block of code? I'm asking this because my login script has to get data from a bans, accounts and achievement table in that specific order. It seems awkward to have three callbacks within other callbacks, and I must make sure that it runs correctly...

Old code (StrickenKid's plugin):
Code:
stock LoginPlayer(playerid)
{
	new string[128], qry[128], res[1050], PlayerStats[72][50], AchievementStatus[22];
//------------------------------------------------------------------------------
	format(qry, sizeof(qry), "UPDATE accounts SET LastIP = '%s', LastVisit = SYSDATE(), LoggedIn = 1 WHERE name = '%s';", PlayerInfo[playerid][PlayerIP], pNick(playerid));
	mysql_query(qry);
//------------------------------------------------------------------------------	
	format(qry, sizeof(qry), "SELECT COUNT(*) FROM bans WHERE accountId = (SELECT accountId FROM accounts WHERE name = '%s') LIMIT 1;", pNick(playerid));
	mysql_query(qry);
	mysql_store_result();
	mysql_fetch_field_num(0, res);
	mysql_free_result();
	if(strval(res))
	{
		format(qry, sizeof(qry), "UPDATE accounts SET LoggedIn = 0 WHERE name = '%s';", pNick(playerid));
		mysql_query(qry);
		SendClientMessage(playerid, COLOUR_SYSTEM, "Nice try ban evading! If you think this ban is unfair, post an unban appeal at "SERVER_SITE"/forum!");
		format(string, sizeof(string), "[Server ban]: %s (%d) - account marked as banned", pNick(playerid), playerid);
		SendClientMessageToAll(COLOUR_ADMIN, string);
		printf(string);
		SendAdminActionToIRC(string);
		SaveLog("Logs", "AttempetdBanEvadings", string);
		format(string, sizeof(string), "%s (%d) - account marked as banned", pNick(playerid), playerid);
		ShowKickBanTextDrawForPlayer(playerid, "banned", "attempting to ban evade");
		return SetTimerEx("DelayedBan", 10, false, "ds", playerid, "attempting to ban evade");
	}
//------------------------------------------------------------------------------	
	format(qry, sizeof(qry), "SELECT * FROM accounts WHERE name = '%s';", pNick(playerid));
	mysql_query(qry);
	mysql_store_result();
	mysql_fetch_row(res, "|");
	explode(PlayerStats, res, "|");
	mysql_free_result();
//------------------------------------------------------------------------------
	PlayerInfo[playerid][LoggedIn] = 1;
 	PlayerInfo[playerid][Registered] = 1;
	PlayerInfo[playerid][accountId] = strval(PlayerStats[0]);
	PlayerInfo[playerid][Level] = strval(PlayerStats[6]);
	SetPlayerScore(playerid, strval(PlayerStats[7]));
 	PlayerInfo[playerid][BankBalance] = strval(PlayerStats[8]);
	SetPlayerMoneyEx(playerid, strval(PlayerStats[9]));
	SetPlayerWantedLevel(playerid, strval(PlayerStats[10]));
	SetPlayerDrunkLevel(playerid, strval(PlayerStats[11]));
	PlayerInfo[playerid][FightStyle] = strval(PlayerStats[12]);
	PlayerInfo[playerid][Skin] = strval(PlayerStats[13]);
  	PlayerInfo[playerid][Kills] = strval(PlayerStats[14]);
   	PlayerInfo[playerid][Deaths] = strval(PlayerStats[15]);
    PlayerInfo[playerid][Donator] = strval(PlayerStats[18]);
	PlayerInfo[playerid][MysterybagsFound] = strval(PlayerStats[19]);
    PlayerInfo[playerid][ReactionTestsWon] = strval(PlayerStats[20]);
    PlayerInfo[playerid][SaveSkin] = strval(PlayerStats[21]);
    PlayerInfo[playerid][AutoIPLogin] =  strval(PlayerStats[22]);
	PlayerInfo[playerid][HoursConnected] = strval(PlayerStats[23]);
    PlayerInfo[playerid][MinutesConnected] = strval(PlayerStats[24]);
    PlayerInfo[playerid][DaysConnected] = strval(PlayerStats[25]);
    PlayerInfo[playerid][RegularPlayer] = strval(PlayerStats[26]);
    PlayerInfo[playerid][NoPM] = strval(PlayerStats[27]);
    PlayerInfo[playerid][GotoEnabled] = strval(PlayerStats[28]);
    PlayerInfo[playerid][PreferedColour] = strval(PlayerStats[29]);
    PlayerInfo[playerid][WatchPMs] = strval(PlayerStats[30]);
    PlayerInfo[playerid][WatchCMDs] = strval(PlayerStats[31]);
    PlayerInfo[playerid][WatchPlayerInfo] = strval(PlayerStats[32]);
    PlayerInfo[playerid][FavouriteVehicle] = strval(PlayerStats[33]);
	PlayerInfo[playerid][Bomb] = strval(PlayerStats[34]);
	PlayerInfo[playerid][RejoinDM] = strval(PlayerStats[35]);
	PlayerInfo[playerid][Drugs] = strval(PlayerStats[36]);
	PlayerInfo[playerid][Seeds] = strval(PlayerStats[37]);
	PlayerInfo[playerid][DuelsDone] = strval(PlayerStats[38]);
	PlayerInfo[playerid][DuelsWon] = strval(PlayerStats[39]);
	PlayerInfo[playerid][CTX] = floatstr(PlayerStats[40]);
    PlayerInfo[playerid][CTY] = floatstr(PlayerStats[41]);
    PlayerInfo[playerid][CTZ] = floatstr(PlayerStats[42]);
    PlayerInfo[playerid][CTInterior] = strval(PlayerStats[43]);
    PlayerInfo[playerid][CTWorld] = strval(PlayerStats[44]);
    // mode similar code
//------------------------------------------------------------------------------
	format(qry, sizeof(qry), "SELECT * FROM achievements WHERE accountId = %d;", strval(PlayerStats[0]));
	mysql_query(qry);
	mysql_store_result();
	mysql_fetch_row(res, "|");
	explode(PlayerStats, res, "|");
	mysql_free_result();
//------------------------------------------------------------------------------
	PlayerInfo[playerid][NeedForSkills_Progress] = strval(PlayerStats[1]);
	PlayerInfo[playerid][Drifter_Progress] = strval(PlayerStats[2]);
	PlayerInfo[playerid][RaceAchievements_Progress] = strval(PlayerStats[3]);
	PlayerInfo[playerid][WTFLottoHax_Progress] = strval(PlayerStats[4]);
	PlayerInfo[playerid][SpankMe_Progress] = strval(PlayerStats[5]);
	PlayerInfo[playerid][Sn1p3r_Progress] = strval(PlayerStats[6]);
	PlayerInfo[playerid][Whore_Progress] = strval(PlayerStats[7]);
	PlayerInfo[playerid][Ninja_Progress] = strval(PlayerStats[8]);
//------------------------------------------------------------------------------
	format(string, sizeof(string), "Welcome back to "DC_RED""SERVER_NAME""DC_GREEN", %s!", pNick(playerid));
	SendClientMessage(playerid, COLOUR_GREEN, string);
//------------------------------------------------------------------------------
	// mode generic code
//------------------------------------------------------------------------------
	CheckForAchievements(playerid);
//------------------------------------------------------------------------------
	return 1;
}
I really don't know how to do this without turning everything into one giant mess..
Reply

So unthreaded queries are unsupported now.

What if we need to load alot of data before the server can even be opened to the public?
Like spawned mission vehicles, job-data, houses, speedcams, businesses, companies, and alot more.

I would rather have the script wait until those queries are finished executing before moving on to the next part (starting timers, loading other data, and more importantly, allow players to login).

I don't want players to be able to login yet as long as the data isn't loaded completely.

Also, I want my debug-lines during each loading process to be displayed in the correct order and before the server says: "Number of vehicles: 17" (this would be when the server is online and waiting for players to join).

I also like to create my database-tables from within the script in case the tables are missing.
When you setup the server for the first time or in case you need to wipe the database, it would be easy to simply delete all tables and let the script re-create them automatically, even with some default data inserted into them as well.

I don't think this can be done with threaded queries.
Reply

That's why I re-added them somewhere around R26 (latest version being R39-4).
I strongly discourage using unthreaded queries though, they're only applicable in very few situations (e.g. being used in OnGameModeInit).
Reply

That's also the only place where I would use them anyways.

But when I think about it, OnGameModeInit could just send all data-loading queries one after the other using tqueries instead of unthreaded queries.

Then all these data-loading callbacks (where it loops through all rows to read the data and store it in arrays) must be finished before any player logs in.

Even when a player logs in before data-loading is finished, his account-load query comes after the data-loading queries and must wait to get executed anyways, so I think it won't matter that much if a player logs in before all data has finished loading.
Tqueries after all are executed sequentially and the queries in OnGameModeInit are executed first anyways.
This will make sure the data is loaded first anyways before any player can actually log in (his query will come last in line).
Reply

Yes, but you'll still have to prohibit incoming players from selecting a character/spawning, because they'll trigger callbacks like OnPlayerRequestClass. If you need to load character classes from the MySQL server first (with threaded queries), that'd be a problem. However, if executing everything in OnGameModeInit, the server won't process incoming connections (or rather connecting players) until OnGameModeInit finished executing.
Reply

I see.

To get your data loaded properly before any player can connect, the only way is to use mysql_query (unthreaded queries).

I'll keep my data-loading functions the way they are then.
Reply

pls help me

how to convert this from R3-2 to R7

PHP Code:
OnGamemodeInit()
{
    
mysql_query("SELECT `id` FROM `goldpot_data` ORDER BY `id` DESC LIMIT 1");
    
mysql_store_result();
    
mysql_fetch_row(line);
    
mysql_free_result();
    
printf("%s"line);
    
goldpot[max_goldpot_id] = strval(line);
    return 
1;

Reply

Nice tutorial, i did learn a lot
Reply

Great tutorial man, good work!
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)