Jump to content
  • Advertisement
  • entries
    109
  • comments
    175
  • views
    117340

Databases, continued.

Sign in to follow this  
Emmanuel Deloget

410 views

The main problem about databases lies in how one can fetch the data from the db. Simply put, storing the result of a SELECT statement is a pain.

Consider this simple table:

CREATE TABLE user (id INTEGER, login TEXT, password TEXT);


Now, a very simple select statement:

SELECT * FROM user;


The C++ typical code to deal with the result of this query is something along the line of:


if (teh_sql_api_exec_function("SELECT * FROM user;")) {
int rowcount = teh_sql_api_getrowcount();
int colcount = teh_sql_api_getcolcount();
for (int r=0; r for (int c=0; c std::string s = teh_sql_api_getstringvalue(c, r);
my_clever_query_object.setdata(c, r, s);
}
}
}

We just have lost the type of our different fields - our id is not more an integer, it is a string. You can avoid this by doing:

teh_sql_type t = teh_sql_api_getdatatype(c);
if (t == teh_sql_integer) {
int i = teh_sql_api_getintvalue(c, r);
my_clever_query_object.setintdata(c, r, i);
} else if (t == teh_sql_string) {
std:string s = teh_sql_api_getstringvalue(c, r);
my_clever_query_object.setstringdata(c, r, s);
} else {
// ... other cases
}

We now know the type of our objects but we can't say anymore that the code is generic. We need to have one method per SQL data type in my_clever_query_object (MySQL has many many different types). We also have to store the values in different places, because a string is not a date and an integer is not a float - C++ is bad at mixing oranges and apples. Thus, you'll need one container per type. It means that you'll have to cleverly store your informations in my_clever_query_object to be able to fetch them back when needed (you'll be able to rename it to my_uber_clever_query_object if you succeed).

There is obviously a better solution to this problem - and you already know its name: variants.

You can implement variant in numerous ways. Qt variant is a basic one - everything is done without using templates (at least, it was true in Qt3. I haven't checked this in Qt4). The Qt variant is very easy to use - and believe it or not but they use it to store database results from their SQL drivers, as shown here.

Another solution is to use typelists[1]. Both the Tiny Template Library variant and the boost.variant use this clever technique.

With variants, we are able to store any kind of data in a single container. Our code becomes:

teh_sql_type t = teh_sql_api_getdatatype(c);
my_cOOl_variant v;
if (t == teh_sql_integer) {
v = teh_sql_api_getintvalue(c, r);
} else if (t == teh_sql_string) {
v = teh_sql_api_getstringvalue(c, r);
} else {
// ... other cases
}
my_clever_query_object.setdata(c, r, v);

That's still a pita, but it's probably the best we can do in C++ :)




[1] typelists are described by A. Alexandrescu in his Modern C++ Design book.
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!