That's ok. I think people who haven't worked on systems where errors cost people millions of dollars, or get people killed, tend to handwave things that promote safety because it's inconvenient.
Hmm, I think that's unfair. I've actually worked on embedded systems used by the police and emergency services, for example. You can't assume that anybody who disagrees with your programming opinions is obviously inexperienced!
There is such a thing as a false sense of security, and I believe static typing gives that. It also encourages casts (usually fine, but occasionally completely unsafe) instead of conversions (sometimes fail, but always safe), and in other cases increases code complexity (again contributing to lack of safety).
I think we'll just disagree on this, but that's ok, because we're not on the same project.
If it's impossible to generate run-time binding types in C++, what's the point of typeof, dynamic_cast, and other things meant to deal with type information at run-time? It seems like the API layer could ask the database for the column type and then use dynamic_cast to properly type the result.
The problem is that, at some point, there needs to be code to handle the end data, and C++ code is all statically generated, so you can't throw arbitrary types at it. It's easy enough to detect what type the database column is storing, and you can create a variable of that type if you want, but you can't return it, since C++ expects you to have defined your return type statically. Nor can you pass it to another function, because C++ generates function calls based on static types. So you can either cast it to void*, like the C people do, or use boost::any, or make some fake types all deriving from a common base class (which is what the dynamic_cast stuff is there for, but which doesn't apply to any of the default types you'd get from a RDDBS)... and either way, you have effectively abandoned static typing and moved to dynamic typing because you have to query types at run-time and call different stuff accordingly. My argument would be therefore that it's not worth doing.
I should also mention that while a generic ad-hoc query API is nice, how often are you going to use that from MUD code? I would hope all the places reading and writing to the database are well defined, and I don't think it's a show-stopper if the admins don't have an "sql" toy command to play with at the prompt -- they can always access the database from outside.
I use it all the time from inside the game. Everyone below the top level is barred from doing anything other than SELECTs, but that alone is a great tool. Want to see the last 15 logins from a certain hostname - easy. Find all weapons with an affect that yields a damroll bonus more than 10% of the object's level? Also easy. List the top 20 mobs killed in the last month in areas with level ranges between 40 and 60? Done. Want to know which classes or races are most popular with female characters and which are popular with males? Simple. Many of these stats are really useful to be able to just pull up as soon as you think you might need them. Sure, we lived without this for years, but then we lived without electricity for millenia too.
I'd rather have the benefits. But it's a choice we all have to make based on our own requirements.
I think you exaggerated slightly what you can and can't do with compile-time bindings. If you know the type of every column in every schema, then you can actually infer the column types of very many queries. In fact, unless you do things with SQL functions, I think you can pretty much infer everything.
Yeah, you can easily find what a column's type is. The problem, as I hope I made clear earlier in this post, is that you can't really do anything useful with that information because at some stage, you need to funnel the data back through a static interface, which essentially means dynamic typing. So you either have to resign yourself to doing run-time conversions, or to pregenerating type-safe code for your queries beforehand. (Or even better, using a dynamically-typed language in the first place which will do it all for you.)