Comment 1 by Thomas Keller, Oct 18, 2010
Ok, I debugged into this and the easiest way to reproduce the problem in 3.7.3 is to do $ mtn db init -d test.mtn $ mtn db set foo foo "" -d test.mtn $ mtn ls vars The empty value column is returned as "" (zero-length string) in sqlite 3.7.2 and 3.6.23 (and possibly other versions which used to work), but as 0 in 3.7.3. According to sqlite's docs ( http://www.sqlite.org/c3ref/column_blob.html) this seems to be correct The return value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer." but apparently was broken in earlier versions (or the paragraph has just been added for 3.7.3). I'm now trying to find out whether there is a valid error case for which sqlite3_column_blob() also returns 0 and if not, our error in database.cc should probably laxed and the null pointer handled properly.
Comment 2 by Timothy Brownawell, Oct 21, 2010
As best I can tell, it only returns zero for empty blobs and NULLs.
So the following should work (committed as
9def7716bcd068fc1929ed8336432bbed775d9ee).
#
# old_revision [97939c9677047b36beef031cce4c1896849a987c]
#
# patch "database.cc"
# from [0afa3ff4bd9c9ee3bc62b10bcf6295a9f5388d64]
# to [8bfff559a0894259fe3668294bd3906ae837129b]
#
============================================================
--- database.cc 0afa3ff4bd9c9ee3bc62b10bcf6295a9f5388d64
+++ database.cc 8bfff559a0894259fe3668294bd3906ae837129b
@@ -1531,12 +1531,19 @@ database_impl::fetch(results & res,
vector<string> row;
for (int col = 0; col < ncol; col++)
{
+ // We never store NULLs, so we should never see one.
+ int const datatype =
sqlite3_column_type(i->second.stmt(), col);
+ E(datatype != SQLITE_NULL, origin::database,
+ F("null result in query: %s") %
query.sql_cmd);
const char * value = (const
char*)sqlite3_column_blob(i->second.stmt(), col);
int bytes = sqlite3_column_bytes(i->second.stmt(),
col);
- E(value, origin::database,
- F("null result in query: %s") %
query.sql_cmd);
- row.push_back(string(value, value + bytes));
- //L(FL("row %d col %d value='%s'") % nrow % col
% value);
+ if (value) {
+ row.push_back(string(value, value + bytes));
+ } else {
+ // sqlite3_column_blob() returns null for zero-length
+ I(bytes == 0);
+ row.push_back(string());
+ }
}
res.push_back(row);
}
Status:
Fixed
Comment 3 by Thomas Keller, Oct 21, 2010
Many thanks Tim for the fix! I got some clarification from Richard Hipp on the issue in the meantime: > There were cases in 3.7.2 and earlier where > sqlite3_column_blob() would return a NULL pointer > for a zero-length blob. And this was documented. > But the behavior was inconsistent, which seemed wrong. > So we modified it to do the same thing every time. Apparently we always go a zero-length blob back and thought this was the correct behaviour. Sadly, this change wasn't mentioned under http://sqlite.org/releaselog/3_7_3.html - maybe it will be in the future.
Sign in to reply to this comment.
Reported by Thomas Keller, Oct 16, 2010