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 
 
Distinguishing between 0 and null

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



Joined: 03 Jan 2005
Posts: 33

PostPosted: Tue Feb 01, 2005 6:37    Post subject: Distinguishing between 0 and null Reply with quote

Quick question. Let's suppose I was using the APS function GetPersistentInt() to retrieve a boolean value from the DB. If the value isn't found the function returns 0. If the value is found and is 0 the function returns 0. How the heck should I distinguish between the two?

I'm actually writing my own function for this, but have run into the same problem. I thought about returning something improbable like -666 if the value wasn't found, but is there a better way?

Although, the more I think about it, maybe I don't need to distinguish between the two. I might get along just fine assuming that a return value of 0 means FALSE, whether it resulted from an actual value of 0 or a missing value. Still, it makes me a little uneasy not being able to determine which case it is.

Anybody else have this problem? How did you deal with it?

Thanks!
Back to top
View user's profile Send private message
Undertowe



Joined: 03 Jan 2005
Posts: 33

PostPosted: Tue Feb 01, 2005 8:07    Post subject: Reply with quote

Here's another question.

Consider the following code from the APS function GetPersistentString():

Code:

if (SQLFirstRow() == SQL_SUCCESS)
    return SQLDecodeSpecialChars(SQLGetData(1));
else
{
    return "";
}


Is this really necessary? If SQLGetData() encounters an empty set, doesn't it just return "" itself? If so, there doesn't seem to be any need to check the result and explicitly return "". Also, there's no harm in passing "" into SQLDecodeSpecialChars(), because the result would be "".

Couldn't we eliminate all but the following and achieve the same effect?

Code:

return SQLDecodeSpecialChars(SQLGetData(1));
Back to top
View user's profile Send private message
NoMercy



Joined: 03 Jan 2005
Posts: 123
Location: UK

PostPosted: Tue Feb 01, 2005 15:10    Post subject: Reply with quote

Mabie it does, mabie it always will, but unless your campaigning for ultimate efficiency then I'd like to stick with the one which is obvious in it's function and resistant to changes in the underlying functions.
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Papillon
x-man


Joined: 28 Dec 2004
Posts: 1060
Location: Germany

PostPosted: Tue Feb 01, 2005 18:42    Post subject: Reply with quote

Undertowe, the call to SQLFirstRow is necessary, and thus there is nothing left to optimize (the test for equality does not really count).

"If the value isn't found the function returns 0. If the value is found and is 0 the function returns 0."

This exactly emulates GetLocalInt's behaviour. If you want something else, you will need to check the return value of SQLFetch and only use the value of SQLGetData() when it returns SQL_SUCCESS, otherwise the variable does not exist.
_________________
Papillon
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Undertowe



Joined: 03 Jan 2005
Posts: 33

PostPosted: Tue Feb 01, 2005 21:11    Post subject: Reply with quote

Thanks for the responses.

Papillon,

I just realized I made a mistake in my second code block. It should have read:

Code:

SQLFetch();
return SQLDecodeSpecialChars(SQLGetData(1));


As for distinguishing between 0 and null, I understand that I could check the result of SQLFetch to determine if the value exists or not. What I'm wondering is, If the value doesn't exist, what should I return? I'm just looking for suggestions.

In the case of GetPersistentInt(), if I decide to return -666 to indicate a missing value, I can't know if the value was missing, or if the value was found and was -666. This is essentially the problem I was facing. How can I know for sure? Again, I'm just looking for suggestions.

"If you want something else, you will need to check the return value of SQLFetch and only use the value of SQLGetData() when it returns SQL_SUCCESS, otherwise the variable does not exist."

Alright, so I know the variable doesn't exist, but how would the calling function know this?

I suppose this is also a problem with GetLocalInt(), as you mention. What if I want to check if a boolean variable exists on a particular object? If I use GetLocalInt() and it returns 0, I still don't know if the value was 0 or if the value wasn't found because the variable doesn't exist. What is one to do?

To give another example of the problem, let's say you normally use SetPersistentInt() to store a PCs hitpoints in pwdata. Then you use GetPersistentInt() and get 0 as the result. Does this mean that the PCs hitpoints are 0 or does it mean that the value was never stored in pwdata? As it stands, you can't know. So, how should one work around this and similar issues of distinguishing between 0 resulting from the value 0 and 0 resulting from a missing variable or dataset?
Back to top
View user's profile Send private message
Papillon
x-man


Joined: 28 Dec 2004
Posts: 1060
Location: Germany

PostPosted: Tue Feb 01, 2005 23:29    Post subject: Reply with quote

I guess it is hard to give a generally acceptable approach to this problem. In programming languages like C, we have a NULL pointer, and in SQL, we have a NULL column value. In NWscript, we do not have something like this, so we have to stick with a convention of return 0 or FALSE for both cases.

If that does not work for you, these are your options:

1) Rethink your scripts and data retrieval. Honestly, all of the code of Avlis can do without running into this problem (and it IS huge, believe me).

2) Return the minimum negative value that an integer can hold in nwscript, which would be ... (looking up in nwnlexicon.com...) -2,147,483,648. I guess that value is somewhat unlikely to exist by happenstance.

3) Do not use a function, but query the database directly when you need a value. Use the return value of SQLFetch to decide if the variables exists or not.
_________________
Papillon
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Undertowe



Joined: 03 Jan 2005
Posts: 33

PostPosted: Wed Feb 02, 2005 1:23    Post subject: Reply with quote

Papillon wrote:
I guess it is hard to give a generally acceptable approach to this problem.


This is what I suspected. I suppose the solution depends on the particular case.

Papillon wrote:
Honestly, all of the code of Avlis can do without running into this problem (and it IS huge, believe me).


Yes, the more I think about it, the more I realize that in actual practice distinguishing between 0 and null probably won't be an issue. It represents more of a problem in theory than in practice.

For instance, I am using a table called 'characters' where each record represents a PC, with columns like 'hitpoints', 'location', 'status', etc. Distinguishing between 0 or "" and null won't be a problem, because by design every PC will always have a value in each column. In other words, there never should be a null value. If there is, the problem is elsewhere.

In another table, 'character_data' I am storing arbitrary key/value pairs (very similar to pwdata). If I query to see if 'bob' is drunk and get a 0 in return, whether or not this resulted from a missing record or 0 amounts to the same thing: not-true, i.e. FALSE. If 'bob' was drunk, it would return 1. Any other result can be considered as FALSE.

Anyways, I'm just thinking (typing) out loud. Thanks again for your help, Papillon. I feel like I have a much better understanding of the issue now, and am reassured that Avlis has never had encountered this problem in practice. Your suggestions for work-arounds also helped clarify my thinking.

Thanks again!
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