2

I have a database in PostgreSQL. And I have sql query (which btw works great in PostgreSQL, so the sql code isn't wrong):

SELECT COUNT(*) as size, creation_date FROM item INNER JOIN raf_item USING (id) INNER JOIN item_detail USING (id) GROUP BY creation_date;

where creation date is defined as creation_date Date; in PostgreSQL.The query returns, for example (depends on what I have in my database):

size | creation_date
21   | 12-31-2012
18   | 04-03-2002

I'm using SOCI + C++ to get data from this query. My whole C++ code:

#include <iostream>
#include <cstdlib>
#include <soci.h>
#include <string>
#include <postgresql/soci-postgresql.h>
using namespace std;

bool connectToDatabase(soci::session &sql, string databaseName, string user, string password)
{
    try
    {
        sql.open(soci::postgresql, "dbname=" +databaseName + " user="+user + " password="+password);
    }
    catch (soci::postgresql_soci_error const & e)
    {
        cerr << "PostgreSQL error: " << e.sqlstate() << " " << e.what() << std::endl;
        return false;
    }
    catch (std::exception const & e)
    {
        cerr << "Some other error: " << e.what() << std::endl;
        return false;
    }
    return true;
}

void getDataFromDatabase(soci::session &sql)
{
    soci::row r;
    sql << "select count(*) as size, creation_date from item inner join raf_item using (id) inner join item_detail using (id) group by creation_date;", soci::into(r);
    for(std::size_t i = 0; i != r.size(); ++i)
    {
        cout << r.get<int>(i);
        tm when = r.get<tm>(i);
        cout << asctime(&when);
    }
}

int main(int argc, char **argv)
{
    soci::session sql;
    bool success = connectToDatabase(sql, "testdb", "testuser", "pass");
    if (success)
    {
        cout << "Connected.\n";
        getDataFromDatabase(sql);
    }

    else
        cout << "Not connected.\n";
    return 0;
}

But I got this error, when I tried to run the application (compilation is fine) :

terminate called after throwing an instance of 'std::bad_cast'
what(): std::bad_cast Interrupt (core dumped)

Please help, when the compilation is fine I really don't know how to fix this.

Maybe the problem is that creation_date is DATE and tm keeps also time ... ? If so, how to fix this?

Brian Brown
  • 3,873
  • 16
  • 48
  • 79
  • Have you tried running your executable in a debugger? – cdhowie Jul 23 '12 at 14:05
  • @cdhowie: Nope, I didn't - I don't know much about debugging unfortunately :/ – Brian Brown Jul 23 '12 at 14:08
  • This would probably be a good way to learn. – cdhowie Jul 23 '12 at 14:08
  • @cdhowie: I know you're right, I just thought that maybe someone had this issue with soci and could help ... I almost sure that the problem is with `creation_date` type ... – Brian Brown Jul 23 '12 at 14:11
  • Well, what have you tried to confirm this? Have you tried to write things to `cout` to verify exactly where the crash is occurring? It looks like you received this crash and just gave up. At least try to figure out which line is triggering the crash. – cdhowie Jul 23 '12 at 14:14
  • @cdhowie: I added try{}catch clause around the piece of code where I try to get data from the database - and that's it, the error is there ... Now, how to fix it? – Brian Brown Jul 23 '12 at 14:16
  • @cdhowie: don't bother yourself anymore, the problem is solved:) – Brian Brown Jul 23 '12 at 14:29
  • @a_horse_with_no_name: ok, thank's I just did it:) – Brian Brown Jul 23 '12 at 14:38

2 Answers2

6

While you did solve your question, the code you posted is more a workaround than the real solution for the problem.

Your problem is, that COUNT(*) returns a value of bigint (or int8) type, as described here, and soci converts bigint to a long long int type, as described in this chart. If the types do not match excatly, a bad_cast exception will be thrown.

Therefore, the code in your question should be cout << r.get<long long>(i); to avoid the bad_cast exception.

niko
  • 1,816
  • 13
  • 13
1

OK, I SOLVED IT BY MYSELF!:)

Heres the code that actualy works fine (I only repleced getDataFromDatabase with this code below):

void getDataFromDatabase(soci::session &sql)
{
    long size;
    string date;

    soci::row r;
    sql << "select count(*) as size, creation from item inner join raf_item using (id) inner join item_detail using (id) group by creation;", soci::into(r);
    for(std::size_t i = 0; i != r.size(); ++i)
    {
        const soci::column_properties & props = r.get_properties(i);

    cout << '<' << props.get_name() << '>';

    switch(props.get_data_type())
    {
    case soci::dt_string:
        cout << r.get<std::string>(i);
        break;
    case soci::dt_double:
        cout << r.get<double>(i);
        break;
    case soci::dt_integer:
        cout << r.get<int>(i);
        break;
    case soci::dt_unsigned_long:
        cout << r.get<unsigned long>(i);
        break;
    case soci::dt_long_long:
        cout << r.get<long long>(i);
        size = r.get<long long>(i);
        break;
    case soci::dt_date:
        std::tm when = r.get<std::tm>(i);
        cout << asctime(&when);
        date = asctime(&when);
        break;
    }

    cout << "\n" << size << "\n";
    cout << "\n" << date << "\n";
}
Brian Brown
  • 3,873
  • 16
  • 48
  • 79