我使用SOCI庫訪問的sqlite3的數據庫:SOCI並不總是返還相同種類對於數字列
rowset<row> rs = (sql.prepare << "select * from my_table");
for (auto it = rs.begin(); it != rs.end(); ++it) {
int some_value = it->get<int>(1);
// ...
}
(這不是我的實際代碼;它很大程度上簡化說明問題。)
現在,大多數時候,這個工作。但是,有時候,行中索引爲1的值是一個字符串,而不是一個int(導致異常爲std::bad_cast
)。相應列的SQL類型爲NUMERIC(8) NOT NULL
。我做了相當多的調試,它看起來像行中的條目數量,它們的值始終是正確的。唯一的問題是這一行的值有時是一個字符串。
這可能是社會中的一個錯誤,也可能是我身邊的錯誤假設。我的假設是一列的返回數據類型總是相同的。類型切換可能會在我的應用程序的一次運行中發生 - 值可能是一個查詢結果中的int值,下一個字符串中的值。
因爲我不知道底層的sqlite3 API,我甚至不確定這個問題是源於sqlite3還是soci。解決方法似乎很簡單:檢查行值的類型,如果它是一個字符串,則將其轉換爲int。但重要的是要知道這是預期的行爲還是錯誤。有人可以對此發表評論嗎?
編輯:
新行得到插入這樣的:
soci::session sql(Connetion::pool);
sql << "INSERT INTO " << NAME << " (REP_TIMESTAMP, REP_EVENT, REP_LTU_ID, REP_SEC_ID) VALUES (:timestamp, :event, :ltuId, :secId)",
use (bo.timestamp),
use (bo.event),
use (bo.ltuId),
use (bo.secId);
凡bo.timestamp
是boost::posix_time::ptime
具有以下映射:
template<> struct type_conversion<boost::posix_time::ptime> {
typedef long long base_type;
static void from_base(const long long& t, indicator& i, boost::posix_time::ptime& target) {
target = Helper::Time::timeFrom(t);
}
static void to_base(const boost::posix_time::ptime& d, long long& target, indicator& i) {
target = Helper::Time::secondsSinceEpoch(d);
i = i_ok;
}
};
Helper::Time
變換ptime
到數自從1970年1月1日以後又回來了。我沒有看到如何使用此代碼可以將字符串加入列REP_TIMESTAMP
。
有趣。但是,我在soci調用的頂部有一個ORM層,它是類型安全的,不能將字符串寫入此列。是否有可能我提供的int值被轉換爲soci或sqlite3 API中的字符串?我想我會嘗試添加檢查,看看會發生什麼。 – flyx
可以使用[type affinity](http://www.sqlite.org/datatype3.html#affinity)轉換類型,但是'NUMERIC'列不能以這種方式獲取字符串。您確實需要檢查以查看字符串來自哪裏。 –
我試圖將檢查添加到我的數據庫佈局。現在每個提交都被「約束失敗」拒絕。 SQLite似乎只有一個'integer'類型,所以即使我在C++端插入'long long',它應該是SQLite的整數,對吧?實際上沒有其他地方的東西被提交到數據庫,所以值*有*要轉換爲字符串在soci或sqlite的某處。 – flyx