SQLite Connect support Datetime

This commit is contained in:
fasiondog 2023-10-22 22:34:05 +08:00
parent c069892c6f
commit 3d9cc793bb
6 changed files with 70 additions and 16 deletions

View File

@ -13,6 +13,7 @@
#include <type_traits>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include "hikyuu/utilities/datetime/Datetime.h"
#include "../../DataType.h"
namespace hku {
@ -40,15 +41,15 @@ public:
* @param driver
* @param sql_statement SQL语句
*/
SQLStatementBase(DBConnectBase* driver, const string& sql_statement);
SQLStatementBase(DBConnectBase *driver, const string &sql_statement);
virtual ~SQLStatementBase() = default;
/** 获取构建时传入的表达式SQL语句 */
const string& getSqlString() const;
const string &getSqlString() const;
/** 获取数据驱动 */
DBConnectBase* getConnect() const;
DBConnectBase *getConnect() const;
/** 执行 SQL */
void exec();
@ -71,6 +72,9 @@ public:
/** 将字符串类型 item 绑定至 idx 指定的 SQL 参数中 */
void bind(int idx, const char *item, size_t len);
/** 将 Datetime 类型 item 绑定至指定的 SQL 参数中 */
void bind(int idx, const Datetime &item);
/** 将 item 的值绑定至 idx 指定的 SQL 参数中 */
void bindBlob(int idx, const std::string &item);
@ -109,6 +113,9 @@ public:
/** 获取 idx 指定的数据至 item */
void getColumn(int idx, std::string &item);
/** 获取 idx 指定的数据至 item */
void getColumn(int idx, Datetime &item);
/** 获取 idx 指定的数据至 item */
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer>::type getColumn(int idx, T &);
@ -128,10 +135,11 @@ public:
virtual bool sub_moveNext() = 0; ///< 子类接口 @see moveNext
virtual uint64_t sub_getLastRowid() = 0; ///< 子类接口 @see getLastRowid();
virtual void sub_bindNull(int idx) = 0; ///< 子类接口 @see bind
virtual void sub_bindInt(int idx, int64_t value) = 0; ///< 子类接口 @see bind
virtual void sub_bindDouble(int idx, double item) = 0; ///< 子类接口 @see bind
virtual void sub_bindText(int idx, const std::string &item) = 0; ///< 子类接口 @see bind
virtual void sub_bindNull(int idx) = 0; ///< 子类接口 @see bind
virtual void sub_bindInt(int idx, int64_t value) = 0; ///< 子类接口 @see bind
virtual void sub_bindDouble(int idx, double item) = 0; ///< 子类接口 @see bind
virtual void sub_bindDatetime(int idx, const Datetime &item) = 0; ///< 子类接口 @see bind
virtual void sub_bindText(int idx, const std::string &item) = 0; ///< 子类接口 @see bind
virtual void sub_bindText(int idx, const char *item, size_t len) = 0; ///< 子类接口 @see bind
virtual void sub_bindBlob(int idx, const std::string &item) = 0; ///< 子类接口 @see bind
virtual void sub_bindBlob(int idx, const char *item, size_t len) = 0; ///< 子类接口 @see bind
@ -139,8 +147,9 @@ public:
virtual int sub_getNumColumns() const = 0; ///< 子类接口 @see getNumColumns
virtual void sub_getColumnAsInt64(int idx, int64_t &) = 0; ///< 子类接口 @see getColumn
virtual void sub_getColumnAsDouble(int idx, double &) = 0; ///< 子类接口 @see getColumn
virtual void sub_getColumnAsText(int idx, std::string &) = 0; ///< 子类接口 @see getColumn
virtual void sub_getColumnAsBlob(int idx, std::string &) = 0; ///< 子类接口 @see getColumn
virtual void sub_getColumnAsDatetime(int idx, Datetime &) = 0; ///< 子类接口 @see getColumn
virtual void sub_getColumnAsText(int idx, std::string &) = 0; ///< 子类接口 @see getColumn
virtual void sub_getColumnAsBlob(int idx, std::string &) = 0; ///< 子类接口 @see getColumn
private:
SQLStatementBase() = delete;
@ -162,7 +171,7 @@ inline const std::string &SQLStatementBase::getSqlString() const {
return m_sql_string;
}
inline DBConnectBase* SQLStatementBase::getConnect() const {
inline DBConnectBase *SQLStatementBase::getConnect() const {
return m_driver;
}
@ -193,6 +202,10 @@ inline void SQLStatementBase::bind(int idx, double item) {
sub_bindDouble(idx, item);
}
inline void SQLStatementBase::bind(int idx, const Datetime &item) {
sub_bindDatetime(idx, item);
}
inline void SQLStatementBase::bindBlob(int idx, const std::string &item) {
sub_bindBlob(idx, item);
}
@ -219,6 +232,10 @@ inline void SQLStatementBase::getColumn(int idx, float &item) {
item = (float)temp;
}
inline void SQLStatementBase::getColumn(int idx, Datetime &item) {
sub_getColumnAsDatetime(idx, item);
}
inline void SQLStatementBase::getColumn(int idx, std::string &item) {
sub_getColumnAsText(idx, item);
}
@ -231,7 +248,7 @@ typename std::enable_if<std::numeric_limits<T>::is_integer>::type SQLStatementBa
template <typename T>
typename std::enable_if<!std::numeric_limits<T>::is_integer>::type SQLStatementBase::bind(
int idx, const T& item) {
int idx, const T &item) {
std::ostringstream sout;
boost::archive::binary_oarchive oa(sout);
oa << BOOST_SERIALIZATION_NVP(item);
@ -240,7 +257,7 @@ typename std::enable_if<!std::numeric_limits<T>::is_integer>::type SQLStatementB
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer>::type SQLStatementBase::getColumn(
int idx, T& item) {
int idx, T &item) {
int64_t temp;
sub_getColumnAsInt64(idx, temp);
item = (T)temp;
@ -248,11 +265,11 @@ typename std::enable_if<std::numeric_limits<T>::is_integer>::type SQLStatementBa
template <typename T>
typename std::enable_if<!std::numeric_limits<T>::is_integer>::type SQLStatementBase::getColumn(
int idx, T& item) {
int idx, T &item) {
string tmp;
try {
sub_getColumnAsBlob(idx, tmp);
} catch (null_blob_exception&) {
} catch (null_blob_exception &) {
return;
}
std::istringstream sin(tmp);
@ -261,7 +278,7 @@ typename std::enable_if<!std::numeric_limits<T>::is_integer>::type SQLStatementB
}
template <typename T, typename... Args>
void SQLStatementBase::bind(int idx, const T& item, const Args&... rest) {
void SQLStatementBase::bind(int idx, const T &item, const Args &...rest) {
bind(idx, item);
bind(idx + 1, rest...);
}

View File

@ -197,6 +197,10 @@ void MySQLStatement::sub_bindDouble(int idx, double item) {
m_param_bind[idx].buffer = boost::any_cast<double>(&buf);
}
void MySQLStatement::sub_bindDatetime(int idx, const Datetime& item) {
HKU_THROW("Not yet implemented");
}
void MySQLStatement::sub_bindText(int idx, const string& item) {
HKU_CHECK(idx < m_param_bind.size(), "idx out of range! idx: {}, total: {}", idx,
m_param_bind.size());
@ -293,6 +297,10 @@ void MySQLStatement::sub_getColumnAsDouble(int idx, double& item) {
}
}
void MySQLStatement::sub_getColumnAsDatetime(int idx, Datetime& item) {
HKU_THROW("Not yet implemented");
}
void MySQLStatement::sub_getColumnAsText(int idx, string& item) {
HKU_CHECK(idx < m_result_buffer.size(), "idx out of range! idx: {}, total: {}",
m_result_buffer.size());

View File

@ -45,6 +45,7 @@ public:
virtual void sub_bindNull(int idx) override;
virtual void sub_bindInt(int idx, int64_t value) override;
virtual void sub_bindDouble(int idx, double item) override;
virtual void sub_bindDatetime(int idx, const Datetime& item) override;
virtual void sub_bindText(int idx, const std::string& item) override;
virtual void sub_bindText(int idx, const char* item, size_t len) override;
virtual void sub_bindBlob(int idx, const std::string& item) override;
@ -53,6 +54,7 @@ public:
virtual int sub_getNumColumns() const override;
virtual void sub_getColumnAsInt64(int idx, int64_t& item) override;
virtual void sub_getColumnAsDouble(int idx, double& item) override;
virtual void sub_getColumnAsDatetime(int idx, Datetime& item) override;
virtual void sub_getColumnAsText(int idx, std::string& item) override;
virtual void sub_getColumnAsBlob(int idx, std::string& item) override;

View File

@ -95,6 +95,14 @@ void SQLiteStatement::sub_bindInt(int idx, int64_t value) {
SQL_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db));
}
void SQLiteStatement::sub_bindDatetime(int idx, const Datetime &item) {
if (item == Null<Datetime>()) {
sub_bindNull(idx);
} else {
sub_bindText(idx, item.str());
}
}
void SQLiteStatement::sub_bindText(int idx, const string &item) {
_reset();
int status =
@ -135,6 +143,12 @@ void SQLiteStatement::sub_getColumnAsDouble(int idx, double &item) {
item = sqlite3_column_double(m_stmt, idx);
}
void SQLiteStatement::sub_getColumnAsDatetime(int idx, Datetime &item) {
std::string date_str;
sub_getColumnAsText(idx, date_str);
item = date_str.empty() ? Datetime() : Datetime(date_str);
}
void SQLiteStatement::sub_getColumnAsText(int idx, std::string &item) {
const char *data = reinterpret_cast<const char *>(sqlite3_column_text(m_stmt, idx));
item = (data != 0) ? std::string(data) : std::string();

View File

@ -40,6 +40,7 @@ public:
virtual void sub_bindNull(int idx) override;
virtual void sub_bindInt(int idx, int64_t value) override;
virtual void sub_bindDouble(int idx, double item) override;
virtual void sub_bindDatetime(int idx, const Datetime &item) override;
virtual void sub_bindText(int idx, const std::string &item) override;
virtual void sub_bindText(int idx, const char *item, size_t len) override;
virtual void sub_bindBlob(int idx, const std::string &item) override;
@ -48,6 +49,7 @@ public:
virtual int sub_getNumColumns() const override;
virtual void sub_getColumnAsInt64(int idx, int64_t &item) override;
virtual void sub_getColumnAsDouble(int idx, double &item) override;
virtual void sub_getColumnAsDatetime(int idx, Datetime &item) override;
virtual void sub_getColumnAsText(int idx, std::string &item) override;
virtual void sub_getColumnAsBlob(int idx, std::string &item) override;

View File

@ -37,12 +37,15 @@ TEST_CASE("test_sqlite") {
"data_int64_t" INTEGER,
"data_double" REAL,
"data_float" REAL,
"create_at" DATETIME,
"null_date" DATETIME,
PRIMARY KEY("id" AUTOINCREMENT)
);)");
}
class T2019 {
TABLE_BIND5(T2019, t2019, name, data_int32_t, data_int64_t, data_double, data_float);
TABLE_BIND7(T2019, t2019, name, data_int32_t, data_int64_t, data_double, data_float,
create_at, null_date);
public:
void reset() {
@ -51,6 +54,8 @@ TEST_CASE("test_sqlite") {
data_int64_t = Null<int64_t>();
data_double = Null<double>();
data_float = Null<float>();
create_at = Null<Datetime>();
null_date = Null<Datetime>();
}
public:
@ -59,6 +64,8 @@ TEST_CASE("test_sqlite") {
int64_t data_int64_t;
double data_double;
float data_float;
Datetime create_at;
Datetime null_date;
};
T2019 x;
@ -67,6 +74,7 @@ TEST_CASE("test_sqlite") {
x.data_int64_t = 3147483647;
x.data_double = 3.1415926;
x.data_float = 3.14f;
x.create_at = Datetime(202310222221);
con->save(x);
T2019 rx;
@ -77,6 +85,9 @@ TEST_CASE("test_sqlite") {
CHECK(rx.data_int64_t == x.data_int64_t);
CHECK(std::abs(rx.data_double - x.data_double) < 0.00001);
CHECK(std::abs(rx.data_float - x.data_float) < 0.00001);
CHECK(rx.create_at == x.create_at);
CHECK(rx.null_date == x.null_date);
CHECK(rx.null_date == Datetime());
con->exec("drop table t2019");
}