Плохое приведение при получении данных из базы данных PostgreSQL с использованием SOCI
У меня есть база данных в PostgreSQL. И у меня есть SQL-запрос (который, кстати, прекрасно работает в PostgreSQL, поэтому 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;
где дата создания определяется как creation_date Date;
в PostgreSQL. Запрос возвращает, например (зависит от того, что у меня в базе данных):
size | creation_date
21 | 12-31-2012
18 | 04-03-2002
Я использую SOCI + C++ для получения данных из этого запроса. Весь мой код на C++:
#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;
}
Но я получил эту ошибку при попытке запустить приложение (компиляция в порядке):
прекращение вызова после создания экземпляра 'std:: bad_cast'
what (): std:: bad_cast Interrupt (ядро сброшено)
Пожалуйста, помогите, когда компиляция в порядке, я действительно не знаю, как это исправить.
Может быть, проблема в том, что creation_date - это DATE, а tm сохраняет и время...? Если так, как это исправить?
2 ответа
Несмотря на то, что вы решили свой вопрос, отправленный вами код - это скорее обходной путь, чем реальное решение проблемы.
Ваша проблема в том, что COUNT(*) возвращает значение типа bigint (или int8), как описано здесь, и soci преобразует bigint в long long int
тип, как описано в этой таблице. Если типы не совпадают в точности, будет выдано исключение bad_cast.
Поэтому код в вашем вопросе должен быть cout << r.get<long long>(i);
чтобы избежать исключения bad_cast.
ОК, я решил это сам!:)
Вот код, который на самом деле работает нормально (я только переписал getDataFromDatabase
с этим кодом ниже):
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";
}