Converting a query (to RC7)
#1

Well since the new version of BlueG's MySQL plugin now only supports threaded queries (which is awesome) it's forcing me to convert all my 350 queries (yes, I counted them, via notepad++). But I don't think I'm getting the gist of it (I've checked AndreT's tutorial)
So can someone convert this query for me, please.

pawn Код:
format(String, 75, "SELECT `Name` FROM `accounts` WHERE `Name`='%s' LIMIT 1",escapename);
mysql_query(String);
mysql_store_result();
if(mysql_num_rows() != 0)
{
    //something
}
else
{
    //something else
}
It's what I use under OnPlayerConnect.
Reply
#2

Heeey!

So you have this awesome query... but why in the name of god are you selecting the name of the player if you already KNOW THE NAME?!

I suppose you mean to actually select something else (and oh yes, player names don't need to be escaped... hopefully there's not any exploit for this in the SA-MP server). So you have this query, was I was saying:
pawn Код:
// OnPlayerConnect
format(query, sizeof(query), "SELECT name FROM accounts WHERE name = '%s' LIMIT 0,1", name);
mysql_function_query(1, query, true, "OnUserDataLoad", "i", playerid);

// OnUserDataLoad
forward OnUserDataLoad(playerid);
public OnUserDataLoad(playerid)
{
    // Get the amount of rows and fields in each row returned by this query.
    new rows, fields;
    cache_get_data(rows, fields);
    // We should only have ONE row, this is why I added the LIMIT 0,1 clause to your query.
    if(rows)
    {
        // We have a row!
        new name[24];
        cache_get_row(0, 0, name);
    }
    else
    {
        // This player most likely does not exist :(
    }
    // Return 1 to make sure that the plugin clears the cache.
    return 1;
}
But keep in mind, selecting the name of a player whose name you already know is stupid!
Reply
#3

Oh about that, see, that query is actually in another (after checking if the player isn't banned, I go on to show them the correct dialog (login or register)). And what I don't get, is this "OnPlayerDataLoad" thingy.

Edit: Here's the entire query:

pawn Код:
mysql_real_escape_string(GetName(playerid),escapename);
    format(String, 76, "SELECT `BanName` FROM `bans` WHERE `BanName` = '%s' LIMIT 1",escapename);
    mysql_function_query(1,String,true,"","i",playerid);
    mysql_store_result();
    if(mysql_num_rows() != 0)
    {
        //something
    }
    if(mysql_num_rows() == 0)
    {
        format(String, 75, "SELECT `Name` FROM `accounts` WHERE `Name` = '%s' LIMIT 1",escapename);
        mysql_query(1,String,false,"i",playerid);
        mysql_store_result();
        if(mysql_num_rows() != 0)
        {
            //something
        }
        if(mysql_num_rows() == 0)
        {
            //something
        }
        mysql_free_result();
    }
    mysql_free_result();
About the escaping names: I was so caught up in escaping strings doing into the database that I forgot all about that.
Reply
#4

This OnPlayerDataLoad thingy is the callback that will be fired. You specify the callback in your mysql_function_query call. This string is the callback that will be called once the query is finished.

This is in OnPlayerConnect:
pawn Код:
format(query, sizeof(query), "SELECT ... FROM bans WHERE BanName = '%s' LIMIT 0,1", name);
mysql_function_query(1, query, "OnBanCheckFinish", "i", playerid);
You run the ban check query.

This is OnBanCheckFinish, the callback called when the ban checking query finishes.
pawn Код:
forward OnBanCheckFinish(playerid);
public OnBanCheckFinish(playerid)
{
    new rows, fields;
    cache_get_data(rows, fields);
    if(rows == 1)
    {
        // player is banned!?
    }
    else
    {
        // player is not banned, so call the data loading query
        new name[24];
        GetPlayerName(playerid, name, sizeof(name));
        format(query, sizeof(query), "SELECT ... FROM accounts WHERE Name = '%s' LIMIT 0,1", name);
        mysql_function_query(1, query, true, "OnPlayerDataLoad", "i", playerid);
    }
}
Now, in case the player is not banned, we will select the player's data from the accounts table. As you can see from the code above, OnPlayerDataLoad(playerid) is the callback that will be fired when our accounts query finishes.

Now the OnPlayerDataLoad query, same as I described before:
pawn Код:
forward OnUserDataLoad(playerid);
public OnUserDataLoad(playerid)
{
    // Get the amount of rows and fields in each row returned by this query.
    new rows, fields;
    cache_get_data(rows, fields);
    // We should only have ONE row, this is why I added the LIMIT 0,1 clause to your query.
    if(rows)
    {
        // We have a row!
        new name[24];
        cache_get_row(0, 0, name);
    }
    else
    {
        // This player most likely does not exist :(
    }
    // Return 1 to make sure that the plugin clears the cache.
    return 1;
}
Now a major thing which I think you still did not understand:
QUERIES LIKE "SELECT name FROM players WHERE name = 'ANDRE'" ARE VERY USELESS - YOU ALREADY KNOW THE NAME. SO SELECT OTHER DATA.
Reply
#5

Ah, just what I did (before reading this post) I just realized that I'll have to send most of my queries to callbacks. That seemed to be my problem. Thanks much!
Reply
#6

What I want to know, do ALL my SELECT queries HAVE to be sent to a callback?
Also, can I send the query to the callback, from inside the callback? (like a self submitting form in HTML)

Example:

pawn Код:
//I call the function here...
CheckAccounts(playerid);

//Somewhere down in the script...
public CheckAccounts(playerid)
{
    format(query,sizeof(query),"SELECT ...");
    mysql_function_query(1,query,true,"CheckAccounts","i",playerid);
    //something else below...
    return 1;
}
Is that possible?
Reply
#7

Quote:

But keep in mind, selecting the name of a player whose name you already know is stupid!

Not really. If you want perfect case matching and something to select, then I don't see why it shouldn't be done. Selecting null has always been problematic for me.
Reply
#8

Quote:
Originally Posted by AndreT
Посмотреть сообщение
This OnPlayerDataLoad thingy is the callback that will be fired. You specify the callback in your mysql_function_query call. This string is the callback that will be called once the query is finished.

This is in OnPlayerConnect:
pawn Код:
format(query, sizeof(query), "SELECT ... FROM bans WHERE BanName = '%s' LIMIT 0,1", name);
mysql_function_query(1, query, "OnBanCheckFinish", "i", playerid);
You run the ban check query.

This is OnBanCheckFinish, the callback called when the ban checking query finishes.
pawn Код:
forward OnBanCheckFinish(playerid);
public OnBanCheckFinish(playerid)
{
    new rows, fields;
    cache_get_data(rows, fields);
    if(rows == 1)
    {
        // player is banned!?
    }
    else
    {
        // player is not banned, so call the data loading query
        new name[24];
        GetPlayerName(playerid, name, sizeof(name));
        format(query, sizeof(query), "SELECT ... FROM accounts WHERE Name = '%s' LIMIT 0,1", name);
        mysql_function_query(1, query, true, "OnPlayerDataLoad", "i", playerid);
    }
}
Now, in case the player is not banned, we will select the player's data from the accounts table. As you can see from the code above, OnPlayerDataLoad(playerid) is the callback that will be fired when our accounts query finishes.

Now the OnPlayerDataLoad query, same as I described before:
pawn Код:
forward OnUserDataLoad(playerid);
public OnUserDataLoad(playerid)
{
    // Get the amount of rows and fields in each row returned by this query.
    new rows, fields;
    cache_get_data(rows, fields);
    // We should only have ONE row, this is why I added the LIMIT 0,1 clause to your query.
    if(rows)
    {
        // We have a row!
        new name[24];
        cache_get_row(0, 0, name);
    }
    else
    {
        // This player most likely does not exist :(
    }
    // Return 1 to make sure that the plugin clears the cache.
    return 1;
}
Now a major thing which I think you still did not understand:
QUERIES LIKE "SELECT name FROM players WHERE name = 'ANDRE'" ARE VERY USELESS - YOU ALREADY KNOW THE NAME. SO SELECT OTHER DATA.
Select queries aren't only used to retrieve data, people also use them for checking if the user exists and other things. If you select *, that would return the whole row which would be worse than just selecting one column.
Reply
#9

Quote:
Originally Posted by Tee
Посмотреть сообщение
What I want to know, do ALL my SELECT queries HAVE to be sent to a callback?
Also, can I send the query to the callback, from inside the callback? (like a self submitting form in HTML)

Example:

pawn Код:
//I call the function here...
CheckAccounts(playerid);

//Somewhere down in the script...
public CheckAccounts(playerid)
{
    format(query,sizeof(query),"SELECT ...");
    mysql_function_query(1,query,true,"CheckAccounts","i",playerid);
    //something else below...
    return 1;
}
Is that possible?
Yea, I'm answering my own question (for those who might have like thoughts).
Yes it is possible but not recommended. I ran a little test both ways (sending the query in the callback and outside). It turns out, sending the same query, inside it's callback would act like an infinite loop (it keeps executing the query)
whereas sending it from outside the callback only executed it once...this means I'll (we'll) have to create callbacks for EVERY single query.
Reply
#10

Quote:
Originally Posted by Tee
Посмотреть сообщение
What I want to know, do ALL my SELECT queries HAVE to be sent to a callback?
Also, can I send the query to the callback, from inside the callback? (like a self submitting form in HTML)

Example:

pawn Код:
//I call the function here...
CheckAccounts(playerid);

//Somewhere down in the script...
public CheckAccounts(playerid)
{
    format(query,sizeof(query),"SELECT ...");
    mysql_function_query(1,query,true,"CheckAccounts","i",playerid);
    //something else below...
    return 1;
}
Is that possible?
If you are using plugin R7, then yes, all queries which return data need to be threaded, and making the script fire a callback once query execution is finished seems to be the only way to do so.

That function cannot be done like that, because it will toggle an infinite loop - what your code does is query, then execute the same callback, then query again, execute the callback, etc.

@SuperViper: SELECT NULL ...
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)