It was recently brought to my attention that there is a strange problem with the REAL SQL Database that prevents you from getting the values out of a database field that you put into it. I’ll illustrate the problem with an example. Assume you have a table schema that looks like this:
CREATE TABLE foo (a INTEGER, b TEXT)
Now, assume you accidently insert a record into table foo with following code:
dim dr as new DatabaseRecord
dr.Column("a") = "hello"
dr.Column("b") = "goodbye"
db.InsertRecord "foo", dr
The problem is that SQLite, the database engine inside the REAL SQL Database, doesn’t care about column types. It will gladly insert any value into any database field. So, for example, you can tell SQLite to insert string data into a field in a column of type integer and SQLite will insert the data without complaint. Unfortunately, the REAL SQL Database itself gives you no way to retrieve the data. To see what I mean, you can attempt the following query for the record we inserted above:
dim rs as RecordSet
rs = db.SQLSelect("SELECT a,b FROM foo")
MsgBox rs.StringValue("a")
If you execute the above code, what you will see in the message box is “0″, instead of “hello”. That’s because the REAL SQL Database sees that the type of ‘a’ column is integer and will automatically attempt to convert data in that column to an integer every time data from that column is retrieved. The data in the database really does exist. But you can’t see it with the REAL SQL Database.
I never realized this problem existed, and in fact, I don’t believe anybody has ever even posted any bugs to the feedback system about it. Most users are probably never trying to put string data into an integer column. But, in my opinion, as much as possible, you should be able to get the original data out of the database one way or another.
This problem doesn’t just occur with integer columns. It occurs with all numeric columns, including doubles as floats as well. It also occurs with booleans, but booleans are a particularly difficult nut to crack, as I’ll explain shortly. There is also a similar problem with dates. The REAL SQL Database always attempts to interpret values in date columns (columns of type DATE, TIME, and TIMESTAMP) as dates and return undefined values if the values can’t be parsed as dates.
I have decided that this bug (and I think it is a bug) must be fixed. As much as possible, I want to make it so you can get the values out of a database field that you put in. Obviously if a field contains string data and you ask for it as an integer, then you may not get back a useful integer. But regardless of what the value is, it should be retrievable.
So I have modified the REAL SQL Database so that if it can’t parse the data in a database field according to the type of that field, it will just return the data as a string. That means that although you may not always be able to retrieve the value of a database field with a type-specific method (IntegerValue, DoubleValue, DateValue, etc.), you should always be able to retrieve the value with StringValue.
The one wrinkle is the boolean type. I need to parse values in boolean columns and tell REALbasic whether those values represent ‘true’ or ‘false’. For various reasons, both ‘0′ and ‘false’ need to represent ‘false’ and ‘1′ and ‘true’ need to represent ‘true’. But that means that whether you put a ‘0′ or a ‘false’ into a database field, it will be retrieved as ‘false’ using StringValue. Similarly, regardless of whether you put ‘1′ or ‘true’ into a database field, it will be retrieved as ‘true’ using StringValue. But, if the value can’t be interpreted as a boolean, then StringValue will return the value exactly.
This change has ramifications to existing code. With booleans, for example, it used to be the case that ‘0′ and ‘false’ were treated as false and everything else was treated as true. Now, ‘0′ and ‘false’ will be treated as false and ‘1′ and ‘true’ will be treated as true and everything else will be undefined. That’s because it will be passed back to REALbasic as a string and then REALbasic itself will deal with attempting to convert it to a boolean value. So all bets are off as to whether the value will be interpreted by REALbasic as true or false. Similarly, dates now really need to be in date format or you will get back a NIL object when you ask for values in a date column using DateValue. But, fetching the values from a field using StringValue should much more reliably return the real value in the database.