I've got a %waveform_channel_count% in my trunk, sounds like a %waveform_channel_count% MISSING query would suit you well, if I ever get around making a release again.
As for the queries, a GET is:
shared_ptr<sqlite3_stmt> stmt = prepare_statement(
"SELECT w.min, w.max, w.rms, w.channels, w.compression "
"FROM file AS f NATURAL JOIN wave AS w "
"WHERE f.location = ? AND f.subsong = ?");
while a remove-dead is:
sqlite3_exec(backing_db.get(), "DELETE FROM file WHERE file_exists(file.location) IS NULL", 0, 0, 0);
where file_exists uses the SDK filesystem::g_exists function.
As such, case semantics are all up to what g_exists does, as I treat locations as opaque things I can throw at fb2k to get files.
As such, I do indeed treat locations differing in case to be different locations, as they very well may be (consider case-sensitive filesystems).
If you've managed to get fb2k to mutate case for a location, then it's not the same file in my world.
I'm not going to use something else than g_exists to test for file existence, as that would just lead to not being able to support things like archives and all.
I'm reluctant to change my locations to ignore case, as down that line lies amusing horribleness with case-sensitive filesystems and collation breakage with oddball locales like the turkish one.