diff --git a/include/dbccpp/DbConnection.h b/include/dbccpp/DbConnection.h index d5842f2..8fce892 100644 --- a/include/dbccpp/DbConnection.h +++ b/include/dbccpp/DbConnection.h @@ -1,3 +1,5 @@ +#pragma once + #ifndef DBCCPP_DBCONNECTION_H__ #define DBCCPP_DBCONNECTION_H__ @@ -5,7 +7,6 @@ #include #include -#include namespace dbc { diff --git a/include/dbccpp/PreparedStatement.h b/include/dbccpp/PreparedStatement.h index 109f9e3..dfc5bbf 100644 --- a/include/dbccpp/PreparedStatement.h +++ b/include/dbccpp/PreparedStatement.h @@ -17,6 +17,7 @@ #else #include #include + #include namespace dbc { namespace stdutil = boost; @@ -190,7 +191,7 @@ class PreparedStatement */ // FIXME: this should be a 64-bit type really // FIXME: information is SQLite-specific - virtual int getLastInsertId() = 0; + virtual __int64 getLastInsertId() = 0; /** Get the underlying SQL statement. */ virtual const char* getSQL() const = 0; @@ -202,7 +203,9 @@ class PreparedStatement // NVI for set() virtual void setString(const int parameterIndex, const std::string& val) = 0; + virtual void setWString(const int parameterIndex, const std::wstring& val) = 0; virtual void setInt(const int parameterIndex, const int val) = 0; + virtual void setInt64(const int parameterIndex, const __int64 val) = 0; virtual void setDouble(const int parameterIndex, const double val) = 0; virtual void setBool(const int parameterIndex, const bool value) = 0; diff --git a/include/dbccpp/ResultSet.h b/include/dbccpp/ResultSet.h index beb2c81..1156d66 100644 --- a/include/dbccpp/ResultSet.h +++ b/include/dbccpp/ResultSet.h @@ -77,8 +77,11 @@ class ResultSet // NVI for get() virtual void getString(const int columnIndex, std::string& out) const = 0; - virtual std::string getString(const int columnIndex) const = 0; + virtual void getWString(const int columnIndex, std::wstring& out) const = 0; + virtual std::string getString(const int columnIndex) const = 0; + virtual std::wstring getWString(const int columnIndex) const = 0; virtual int getInt(const int columnIndex) const = 0; + virtual __int64 getInt64(const int columnIndex) const = 0; virtual double getDouble(const int columnIndex) const = 0; virtual bool getBool(const int columnIndex) const = 0; }; diff --git a/include/dbccpp/SubscriptProxy.h b/include/dbccpp/SubscriptProxy.h index 996c6b7..315314a 100644 --- a/include/dbccpp/SubscriptProxy.h +++ b/include/dbccpp/SubscriptProxy.h @@ -6,6 +6,8 @@ namespace dbc { +#pragma warning(disable:4512)//warning C4512: 'SubscriptProxy' : assignment operator could not be generated - because of const member variables. + class SubscriptProxy { public: @@ -16,6 +18,9 @@ class SubscriptProxy operator int () const { return _results.getInt(_index); } + operator __int64 () const + { return _results.getInt64(_index); } + operator double () const { return _results.getDouble(_index); } @@ -25,11 +30,14 @@ class SubscriptProxy operator std::string () const { return _results.getString(_index); } + operator std::wstring () const + { return _results.getWString(_index); } + private: const ResultSet& _results; const int _index; }; - +#pragma warning(default:4512) } #endif /* SUBSCRIPTPROXY_H */ diff --git a/src/DbConnectionFactory.h b/src/DbConnectionFactory.h index b61eb75..e88df10 100644 --- a/src/DbConnectionFactory.h +++ b/src/DbConnectionFactory.h @@ -25,9 +25,6 @@ class DbConnectionFactory typedef dbconnection_transferable_ptr (*CreateDbConnectionCallback)(const std::string&); typedef std::map CallbackMap; - bool registerDbConnectionCreator(const std::string& driverName, - CreateDbConnectionCallback creator); - dbconnection_transferable_ptr createDbConnection(const std::string& driverName, const std::string& params); diff --git a/src/PreparedStatement.cpp b/src/PreparedStatement.cpp index 523f856..6cbbe65 100644 --- a/src/PreparedStatement.cpp +++ b/src/PreparedStatement.cpp @@ -7,6 +7,10 @@ template<> void PreparedStatement::set(const int parameterIndex, const int val) { setInt(parameterIndex, val); } +template<> +void PreparedStatement::set<__int64>(const int parameterIndex, const __int64 val) +{ setInt64(parameterIndex, val); } + template<> void PreparedStatement::set(const int parameterIndex, const bool val) { setBool(parameterIndex, val); } @@ -16,7 +20,11 @@ void PreparedStatement::set(const int parameterIndex, const double val) { setDouble(parameterIndex, val); } template<> -void PreparedStatement::set(const int parameterIndex, const char* val) +void PreparedStatement::set(const int parameterIndex, const char* const val) +{ setString(parameterIndex, val); } + +template<> +void PreparedStatement::set(const int parameterIndex, const char* const val) { setString(parameterIndex, val); } template<> @@ -24,4 +32,19 @@ void PreparedStatement::set(const int parameterIndex, const std::string& val) { setString(parameterIndex, val); } -} +template<> +void PreparedStatement::set(const int parameterIndex, + wchar_t const* const val) +{ setWString(parameterIndex, std::wstring(val)); } + +template<> +void PreparedStatement::set(const int parameterIndex, + wchar_t const* const val) +{ setWString(parameterIndex, std::wstring(val)); } + +template<> +void PreparedStatement::set(const int parameterIndex, + const std::wstring& val) +{ setWString(parameterIndex, val); } + +}//dbc namespace diff --git a/src/ResultSet.cpp b/src/ResultSet.cpp index 837db50..702e569 100644 --- a/src/ResultSet.cpp +++ b/src/ResultSet.cpp @@ -1,3 +1,4 @@ + #include #include @@ -10,6 +11,12 @@ int ResultSet::get(const int columnIndex) const return getInt(columnIndex); } +template <> +__int64 ResultSet::get(const int columnIndex) const +{ + return getInt64(columnIndex); +} + template <> double ResultSet::get(const int columnIndex) const { @@ -34,6 +41,18 @@ void ResultSet::get(const int columnIndex, std::string& out) const return getString(columnIndex, out); } +template <> +std::wstring ResultSet::get(const int columnIndex) const +{ + return getWString(columnIndex); +} + +template <> +void ResultSet::get(const int columnIndex, std::wstring& out) const +{ + return getWString(columnIndex, out); +} + const SubscriptProxy ResultSet::operator[] (const int index) const { return SubscriptProxy(*this, index); diff --git a/src/sqlite/SQLitePreparedStatement.cpp b/src/sqlite/SQLitePreparedStatement.cpp index 2ef83c7..46d0db4 100644 --- a/src/sqlite/SQLitePreparedStatement.cpp +++ b/src/sqlite/SQLitePreparedStatement.cpp @@ -38,6 +38,16 @@ sqlite3_stmt* init_statement(dbc::SQLiteConnection& db, const std::string& sql) namespace dbc { +#include + std::string toMBStr(std::wstring const& str) + { + std::string mbstr( str.size(), 0 ); + size_t res; + wcstombs_s(&res, &mbstr[0], mbstr.size(), &str[0], str.size() ); + return mbstr; + } + + #define THROW_IF_SET_STMT_NOT_OK(retval, func_name, val) \ if (retval != SQLITE_OK) \ { \ @@ -46,6 +56,14 @@ namespace dbc throw SQLiteSqlError(_db, err.str(), getSQL()); \ } +#define THROW_IF_SET_STMT_NOT_OK_W(retval, func_name, val) \ + if (retval != SQLITE_OK) \ + { \ + std::wostringstream err; \ + err << func_name L"(" << index << L", " << val << L") failed"; \ + throw SQLiteSqlError(_db, toMBStr(err.str()), getSQL()); \ + } + // sql has to be UTF-8 SQLitePreparedStatement::SQLitePreparedStatement(const std::string& sql, SQLiteConnection& db) : @@ -104,9 +122,9 @@ void SQLitePreparedStatement::doReset() throw SQLiteSqlError(_db, "sqlite3_reset() failed", getSQL()); } -int SQLitePreparedStatement::getLastInsertId() +__int64 SQLitePreparedStatement::getLastInsertId() { - return static_cast(sqlite3_last_insert_rowid(_db.handle())); + return static_cast<__int64>(sqlite3_last_insert_rowid(_db.handle())); } const char* SQLitePreparedStatement::getSQL() const @@ -121,6 +139,13 @@ void SQLitePreparedStatement::setInt(const int index, const int value) THROW_IF_SET_STMT_NOT_OK(ret, "sqlite3_bind_int", value); } +void SQLitePreparedStatement::setInt64(const int index, const __int64 value) +{ + _param_tracker.setParameter(index); + int ret = sqlite3_bind_int64(_statement.get(), index, value); + THROW_IF_SET_STMT_NOT_OK(ret, "sqlite3_bind_int64", value); +} + void SQLitePreparedStatement::setBool(const int index, const bool value) { _param_tracker.setParameter(index); @@ -147,6 +172,18 @@ void SQLitePreparedStatement::setString(const int index, const std::string& valu (value.length() < 50 ? value : value.substr(0, 47) + "...")); } +void SQLitePreparedStatement::setWString(const int index, const std::wstring& value) +{ + _param_tracker.setParameter(index); + // Note that SQLITE_TRANSIENT makes copy of the data. + // This may be expensive if it is large. + + int ret = sqlite3_bind_text16(_statement.get(), index, + value.c_str(), -1, SQLITE_TRANSIENT); + THROW_IF_SET_STMT_NOT_OK_W(ret, L"sqlite3_bind_text16", + (value.length() < 50 ? value : value.substr(0, 47) + L"...")); +} + void SQLitePreparedStatement::setNull(const int index) { _param_tracker.setParameter(index); diff --git a/src/sqlite/SQLitePreparedStatement.h b/src/sqlite/SQLitePreparedStatement.h index 942332c..4d3f7f2 100644 --- a/src/sqlite/SQLitePreparedStatement.h +++ b/src/sqlite/SQLitePreparedStatement.h @@ -27,7 +27,7 @@ class SQLitePreparedStatement : public PreparedStatement virtual void setNull(const int index); - virtual int getLastInsertId(); + virtual __int64 getLastInsertId(); virtual const char* getSQL() const; @@ -39,7 +39,10 @@ class SQLitePreparedStatement : public PreparedStatement protected: virtual void setString(const int parameterIndex, const std::string& val); + virtual void setWString(const int parameterIndex, const std::wstring& val); + //virtual void setString(const int parameterIndex, const CString& val); virtual void setInt(const int parameterIndex, const int val); + virtual void setInt64(const int parameterIndex, const __int64 val); virtual void setDouble(const int parameterIndex, const double val); virtual void setBool(const int parameterIndex, const bool value); diff --git a/src/sqlite/SQLiteResultSet.cpp b/src/sqlite/SQLiteResultSet.cpp index 78d4e9f..02a1d03 100644 --- a/src/sqlite/SQLiteResultSet.cpp +++ b/src/sqlite/SQLiteResultSet.cpp @@ -92,6 +92,26 @@ std::string SQLiteResultSet::getString(const int columnIndex) const return result ? reinterpret_cast(result) : ""; } +void SQLiteResultSet::getWString(const int columnIndex, std::wstring& out) const +{ + checkRowAndColumn(columnIndex); + + const void* result = sqlite3_column_text16(_statement.handle(), + columnIndex); + + out = result ? reinterpret_cast(result) : L""; +} + +std::wstring SQLiteResultSet::getWString(const int columnIndex) const +{ + checkRowAndColumn(columnIndex); + + const void* result = sqlite3_column_text16(_statement.handle(), + columnIndex); + + return result ? reinterpret_cast(result) : L""; +} + int SQLiteResultSet::getInt(const int columnIndex) const { checkRowAndColumn(columnIndex); @@ -99,6 +119,13 @@ int SQLiteResultSet::getInt(const int columnIndex) const return sqlite3_column_int(_statement.handle(), columnIndex); } +__int64 SQLiteResultSet::getInt64(const int columnIndex) const +{ + checkRowAndColumn(columnIndex); + + return sqlite3_column_int64(_statement.handle(), columnIndex); +} + bool SQLiteResultSet::getBool(const int columnIndex) const { checkRowAndColumn(columnIndex); diff --git a/src/sqlite/SQLiteResultSet.h b/src/sqlite/SQLiteResultSet.h index 3cdfeb8..b35e66b 100644 --- a/src/sqlite/SQLiteResultSet.h +++ b/src/sqlite/SQLiteResultSet.h @@ -24,8 +24,11 @@ class SQLiteResultSet : public ResultSet protected: virtual void getString(const int columnIndex, std::string& out) const; + virtual void getWString(const int columnIndex, std::wstring& out) const; virtual std::string getString(const int columnIndex) const; + virtual std::wstring getWString(const int columnIndex) const; virtual int getInt(const int columnIndex) const; + virtual __int64 getInt64(const int columnIndex) const; virtual double getDouble(const int columnIndex) const; virtual bool getBool(const int columnIndex) const;