logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
NWNX ODBC Improvement?

 
Post new topic   Reply to topic    nwnx.org Forum Index -> Database related
View previous topic :: View next topic  
Author Message
pdwalker



Joined: 09 Aug 2005
Posts: 22

PostPosted: Sun Aug 21, 2005 19:53    Post subject: NWNX ODBC Improvement? Reply with quote

Hi,

I've been having a fiddle with the NWNX ODBC interface and I've noticed one thing that I think could be used to improve how the inerface operates

With SELECT statements, you can use the SQLFetch function to determine if your select statement returned any rows.

Unfortunately, with UPDATEs, you do not get any feedback as to whether the updated succeeded (e.g. when updating a non existing record set). As a result a select has to be coded in, tested for an error and then the choice between an update or insert decided. This results in double the number of queries that have to be run in order update records.

Would it be possible to return an value to indicate the success or failure of a statement to avoid this extra coding?

e.g. (using SetPersistentString as an example)

Code:

    string sSQL = "SELECT player FROM " + sTable + " WHERE player='" + sPlayer +
        "' AND tag='" + sTag + "' AND name='" + sVarName + "'";
    SQLExecDirect(sSQL);

    if (SQLFetch() == SQL_SUCCESS)
    {
        // row exists
        sSQL = "UPDATE " + sTable + " SET val='" + sValue +
            "',expire=" + IntToString(iExpiration) + " WHERE player='" + sPlayer +
            "' AND tag='" + sTag + "' AND name='" + sVarName + "'";
        SQLExecDirect(sSQL);
    }
    else
    {
        // row doesn't exist
        sSQL = "INSERT INTO " + sTable + " (player,tag,name,val,expire) VALUES" +
            "('" + sPlayer + "','" + sTag + "','" + sVarName + "','" +
            sValue + "'," + IntToString(iExpiration) + ")";
        SQLExecDirect(sSQL);
    }


becomes

Code:

    sSQL = "UPDATE " + sTable + " SET val='" + sValue +
        "',expire=" + IntToString(iExpiration) + " WHERE player='" + sPlayer +
        "' AND tag='" + sTag + "' AND name='" + sVarName + "'";
    if (SQLExecDirect(sSQL))
    {
        // error, record not updated, insert it instead as it probably does not exist
        sSQL = "INSERT INTO " + sTable + " (player,tag,name,val,expire) VALUES" +
            "('" + sPlayer + "','" + sTag + "','" + sVarName + "','" +
            sValue + "'," + IntToString(iExpiration) + ")";
        SQLExecDirect(sSQL);
    }   


The first bit of code always runs two queries.

The second bit of code only runs two queries for newly created records. In a persistent world where more values would be updated rather than inserted, it results in half the number of queries.

It is possible that this functionality exists and that I have missed it, so I would love to have someone point it out to me.

Comments? Suggestions?

Thanks in advance.

- Paul
Back to top
View user's profile Send private message
Papillon
x-man


Joined: 28 Dec 2004
Posts: 1060
Location: Germany

PostPosted: Mon Aug 22, 2005 14:01    Post subject: Reply with quote

From the top of my head I'd say that UPDATE and INSERT do not return result values. I can see some issues about interpreting a zero result (as is the case in your update example) as an error, but the idea itself is good.
_________________
Papillon
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
pdwalker



Joined: 09 Aug 2005
Posts: 22

PostPosted: Mon Aug 22, 2005 16:06    Post subject: Reply with quote

Typically, the convention for inserts, deletes, updates and selects is to return the number of rows inserted, deleted, affected or selected.

This is the case with JDBC.

I've just peaked into the odbc api's and...ack! The api seems a little clunky to me. It looks like you would have to fiddle with the SQLGetDiagRec function to get more useful information (maybe, not sure - didnt read further)

The SQLExecDirect function does at least return an error if the statement fails, so in the case of updates, you can use that error as a guide that you have to follow it up with an insert.

I see from the docs that:
Quote:
If SQLExecDirect executes a searched update or delete statement that does not affect any rows at the data source, the call to SQLExecDirect returns SQL_NO_DATA.


This information could be used to eliminate the redundant selects before updates.

- Paul
Back to top
View user's profile Send private message
Lokey



Joined: 02 Jan 2005
Posts: 158

PostPosted: Wed Aug 24, 2005 7:08    Post subject: Kneejerk reaction Reply with quote

I don't really follow why you set up your SQL statements that way though.

It'll make the SQL statement more messy, but won't require multiple connects if you just did:

INSERT (statement) ON DUPLICATE KEY UPDATE (statement);
_________________
Neversummer PW NWNx powered mayhem Wink
Back to top
View user's profile Send private message
Vladiat0r



Joined: 17 Jun 2005
Posts: 25

PostPosted: Wed Aug 24, 2005 11:06    Post subject: Re: Kneejerk reaction Reply with quote

Lokey wrote:
I don't really follow why you set up your SQL statements that way though.

It'll make the SQL statement more messy, but won't require multiple connects if you just did:

INSERT (statement) ON DUPLICATE KEY UPDATE (statement);
I believe it's because this requires minimum version MySQL 4.1
Who knows what other Databases support this?
Back to top
View user's profile Send private message
pdwalker



Joined: 09 Aug 2005
Posts: 22

PostPosted: Wed Aug 24, 2005 17:44    Post subject: Re: Kneejerk reaction Reply with quote

Lokey wrote:
I don't really follow why you set up your SQL statements that way though.

It'll make the SQL statement more messy, but won't require multiple connects if you just did:

INSERT (statement) ON DUPLICATE KEY UPDATE (statement);


It is non standard SQL and does not work with Oracle, SQL Server or Postgres. Good enough reason not to use it, but instead use the more conventional syntax.

- Paul
Back to top
View user's profile Send private message
Gryphyn



Joined: 20 Jan 2005
Posts: 431

PostPosted: Fri Aug 26, 2005 7:04    Post subject: Reply with quote

There is a MySQL API call that returns just this data.

MySQL Reference Manual :: 24.2.7.1 mysql_stmt_affected_rows()

mysql_stmt_affected_rows() my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt) Description Returns ... be called immediately after mysql_stmt_execute() for UPDATE , DELETE , or INSERT statements. For SELECT statements, mysql_stmt_affected_rows() works like mysql_num_rows() . This function was added in MySQL 4.1.0. Return Values An integer greater than zero

This could possibly be added as an extra 'NWNX_Function'.
The result could even be used to control 'loops', as you know how many records were/are affected.

Cheers
Gryphyn
Back to top
View user's profile Send private message
Acrodania



Joined: 02 Jan 2005
Posts: 208

PostPosted: Fri Aug 26, 2005 17:57    Post subject: Reply with quote

The important line being right here.....

Gryphyn wrote:

There is a MySQL API call that returns just this data.
This function was added in MySQL 4.1.0. Return Values An integer greater than zero


All but one of the NWNX installs I know of are running 4.0.XX, plus that series is still considered "current".

API calls that are not used in current implementations shouldn't be added by default...
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> Database related All times are GMT + 2 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group