From 89c252bc599456a6d55fc538697940009686ded6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 8 Nov 2022 14:12:59 +0000 Subject: [PATCH 1/9] add clang-format --- .clang-format | 22 +++++++++++++++++ CMakeLists.txt | 6 +++-- cmake/Misc.cmake | 24 +++++++++++++++++++ src/CMakeLists.txt | 59 ++++++++++++++++++++++++---------------------- 4 files changed, 81 insertions(+), 30 deletions(-) create mode 100644 .clang-format create mode 100644 cmake/Misc.cmake diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..7f6fb403 --- /dev/null +++ b/.clang-format @@ -0,0 +1,22 @@ +Language: Cpp + +BasedOnStyle: Google +BreakBeforeBraces: Custom +# AllowShortIfStatementsOnASingleLine: Never +# AllowAllConstructorInitializersOnNextLine: false +# BreakConstructorInitializers: BeforeComma +# KeepEmptyLinesAtTheStartOfBlocks: true +# BraceWrapping: +# AfterCaseLabel: true +# AfterClass: true +# AfterControlStatement: true +# AfterEnum: true +# AfterExternBlock: true +# AfterFunction: true +# AfterNamespace: true +# AfterStruct: true +# BeforeCatch: true +# BeforeElse: true +# SplitEmptyFunction: false +# SplitEmptyNamespace: false +# SplitEmptyRecord: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 01adf7c5..7159856c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.14) + project(RMariaDB VERSION 0.1.0) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") +include(Misc) -add_subdirectory(src) \ No newline at end of file +add_subdirectory(src) diff --git a/cmake/Misc.cmake b/cmake/Misc.cmake new file mode 100644 index 00000000..5665d4c3 --- /dev/null +++ b/cmake/Misc.cmake @@ -0,0 +1,24 @@ +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# clang-format support +function(add_clang_format_target) + set(options) + set(oneValueArgs) + set(multiValueArgs SOURCES) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) + if(NOT ${PROJECT_NAME}_CLANG_FORMAT_BINARY) + find_program(${PROJECT_NAME}_CLANG_FORMAT_BINARY clang-format) + endif() + + message(STATUS ${ARG_SOURCES}) + + if(${PROJECT_NAME}_CLANG_FORMAT_BINARY) + add_custom_target(clang-format + COMMAND ${${PROJECT_NAME}_CLANG_FORMAT_BINARY} --verbose + -i ${ARG_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) + + message(STATUS "Format the project using the `clang-format` target (i.e: cmake --build build --target clang-format).\n") + endif() +endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ddfb3858..3aefdb80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,36 +4,39 @@ get_filename_component(MYSQL_PATH ${MYSQL} DIRECTORY) find_file(POSTGRESSQL postgresql/plogr.h) get_filename_component(POSTGRESSQL_PATH ${POSTGRESSQL} DIRECTORY) -add_library(RMariaDB - connection.cpp - DbConnection.cpp - DbConnection.h - DbResult.cpp - DbResult.h - DbResultImplDecl.h - DbResultImpl.h - driver.cpp - integer64.h - MariaBinding.cpp - MariaBinding.h - MariaResult.cpp - MariaResult.h - MariaResultImpl.cpp - MariaResultImpl.h - MariaResultPrep.cpp - MariaResultPrep.h - MariaResultSimple.cpp - MariaResultSimple.h - MariaRow.cpp - MariaRow.h - MariaTypes.cpp - MariaTypes.h - pch.h - RcppExports.cpp - result.cpp - RMariaDB_types.h +set(SOURCES + connection.cpp + DbConnection.cpp + DbConnection.h + DbResult.cpp + DbResult.h + DbResultImplDecl.h + DbResultImpl.h + driver.cpp + integer64.h + MariaBinding.cpp + MariaBinding.h + MariaResult.cpp + MariaResult.h + MariaResultImpl.cpp + MariaResultImpl.h + MariaResultPrep.cpp + MariaResultPrep.h + MariaResultSimple.cpp + MariaResultSimple.h + MariaRow.cpp + MariaRow.h + MariaTypes.cpp + MariaTypes.h + pch.h + RcppExports.cpp + result.cpp + RMariaDB_types.h ) +add_library(RMariaDB ${SOURCES}) +add_clang_format_target(SOURCES ${SOURCES}) + target_include_directories(RMariaDB PUBLIC "/usr/share/R/include" "/home/gitpod/R/x86_64-pc-linux-gnu-library/3.6/Rcpp/include/" From 0ee6ff941580314cb29b07bb757ba4b80b4f012e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 8 Nov 2022 14:15:30 +0000 Subject: [PATCH 2/9] format code --- .clang-format | 19 -- .gitpod.Dockerfile | 1 + src/DbConnection.cpp | 114 +++++----- src/DbConnection.h | 26 ++- src/DbResult.cpp | 32 +-- src/DbResult.h | 15 +- src/MariaBinding.cpp | 214 ++++++++++--------- src/MariaBinding.h | 7 +- src/MariaResult.cpp | 20 +- src/MariaResult.h | 16 +- src/MariaResultImpl.cpp | 9 +- src/MariaResultImpl.h | 6 +- src/MariaResultPrep.cpp | 96 ++++----- src/MariaResultPrep.h | 10 +- src/MariaResultSimple.cpp | 45 ++-- src/MariaResultSimple.h | 9 +- src/MariaRow.cpp | 203 +++++++++--------- src/MariaRow.h | 8 +- src/MariaTypes.cpp | 211 +++++++++---------- src/MariaTypes.h | 8 +- src/RMariaDB_types.h | 6 +- src/RcppExports.cpp | 429 +++++++++++++++++++++----------------- src/connection.cpp | 56 ++--- src/driver.cpp | 19 +- src/integer64.h | 2 +- src/pch.h | 1 - src/result.cpp | 43 ++-- 27 files changed, 773 insertions(+), 852 deletions(-) diff --git a/.clang-format b/.clang-format index 7f6fb403..f01f27cd 100644 --- a/.clang-format +++ b/.clang-format @@ -1,22 +1,3 @@ Language: Cpp BasedOnStyle: Google -BreakBeforeBraces: Custom -# AllowShortIfStatementsOnASingleLine: Never -# AllowAllConstructorInitializersOnNextLine: false -# BreakConstructorInitializers: BeforeComma -# KeepEmptyLinesAtTheStartOfBlocks: true -# BraceWrapping: -# AfterCaseLabel: true -# AfterClass: true -# AfterControlStatement: true -# AfterEnum: true -# AfterExternBlock: true -# AfterFunction: true -# AfterNamespace: true -# AfterStruct: true -# BeforeCatch: true -# BeforeElse: true -# SplitEmptyFunction: false -# SplitEmptyNamespace: false -# SplitEmptyRecord: false diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index 7444bf79..63587420 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -7,6 +7,7 @@ RUN sudo apt install -y \ r-base \ ccache \ cmake \ + clang-format \ mariadb-server mariadb-client \ # Install dependencies for devtools package libharfbuzz-dev libfribidi-dev diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index efb60641..b472b0d4 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -1,12 +1,10 @@ -#include "pch.h" #include "DbConnection.h" + #include "DbResult.h" +#include "pch.h" -DbConnection::DbConnection() : - pConn_(NULL), - pCurrentResult_(NULL), - transacting_(false) -{ +DbConnection::DbConnection() + : pConn_(NULL), pCurrentResult_(NULL), transacting_(false) { LOG_VERBOSE; } @@ -19,15 +17,16 @@ DbConnection::~DbConnection() { } } -void DbConnection::connect(const Nullable& host, const Nullable& user, - const Nullable& password, const Nullable& db, - unsigned int port, const Nullable& unix_socket, - unsigned long client_flag, const Nullable& groups, - const Nullable& default_file, - const Nullable& ssl_key, const Nullable& ssl_cert, - const Nullable& ssl_ca, const Nullable& ssl_capath, - const Nullable& ssl_cipher, - int timeout, bool reconnect) { +void DbConnection::connect( + const Nullable& host, const Nullable& user, + const Nullable& password, const Nullable& db, + unsigned int port, const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, bool reconnect) { LOG_VERBOSE; this->pConn_ = mysql_init(NULL); @@ -46,33 +45,30 @@ void DbConnection::connect(const Nullable& host, const NullablepConn_, - ssl_key.isNull() ? NULL : as(ssl_key).c_str(), - ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), - ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), - ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), - ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str() - ); + this->pConn_, + ssl_key.isNull() ? NULL : as(ssl_key).c_str(), + ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), + ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), + ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), + ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); } if (timeout > 0) { - mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, - &timeout); + mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); } if (reconnect) { my_bool reconnect_ = 1; - mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void *)&reconnect_); + mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); } LOG_VERBOSE; - if (!mysql_real_connect(this->pConn_, - host.isNull() ? NULL : as(host).c_str(), - user.isNull() ? NULL : as(user).c_str(), - password.isNull() ? NULL : as(password).c_str(), - db.isNull() ? NULL : as(db).c_str(), - port, - unix_socket.isNull() ? NULL : as(unix_socket).c_str(), - client_flag)) { + if (!mysql_real_connect( + this->pConn_, host.isNull() ? NULL : as(host).c_str(), + user.isNull() ? NULL : as(user).c_str(), + password.isNull() ? NULL : as(password).c_str(), + db.isNull() ? NULL : as(db).c_str(), port, + unix_socket.isNull() ? NULL : as(unix_socket).c_str(), + client_flag)) { std::string error = mysql_error(this->pConn_); mysql_close(this->pConn_); this->pConn_ = NULL; @@ -85,23 +81,19 @@ void DbConnection::disconnect() { if (!is_valid()) return; if (has_query()) { - warning( - "%s\n%s", - "There is a result object still in use.", - "The connection will be automatically released when it is closed" - ); + warning("%s\n%s", "There is a result object still in use.", + "The connection will be automatically released when it is closed"); } try { mysql_close(get_conn()); - } catch (...) {}; + } catch (...) { + }; pConn_ = NULL; } -bool DbConnection::is_valid() { - return !!get_conn(); -} +bool DbConnection::is_valid() { return !!get_conn(); } void DbConnection::check_connection() { if (!is_valid()) { @@ -110,26 +102,21 @@ void DbConnection::check_connection() { } List DbConnection::info() { - return - List::create( + return List::create( _["host"] = std::string(pConn_->host), _["username"] = std::string(pConn_->user), _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), _["con.type"] = std::string(mysql_get_host_info(pConn_)), _["db.version"] = std::string(mysql_get_server_info(pConn_)), _["port"] = NA_INTEGER, - _["protocol.version"] = (int) mysql_get_proto_info(pConn_), - _["thread.id"] = (int) mysql_thread_id(pConn_) - ); + _["protocol.version"] = (int)mysql_get_proto_info(pConn_), + _["thread.id"] = (int)mysql_thread_id(pConn_)); } -MYSQL* DbConnection::get_conn() { - return pConn_; -} +MYSQL* DbConnection::get_conn() { return pConn_; } SEXP DbConnection::quote_string(const String& input) { - if (input == NA_STRING) - return get_null_string(); + if (input == NA_STRING) return get_null_string(); const char* input_cstr = input.get_cstring(); size_t input_len = strlen(input_cstr); @@ -138,7 +125,8 @@ SEXP DbConnection::quote_string(const String& input) { std::string output = "'"; output.resize(input_len * 2 + 3); - size_t end = mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); + size_t end = + mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); output.resize(end + 1); output.append("'"); @@ -151,12 +139,10 @@ SEXP DbConnection::get_null_string() { } void DbConnection::set_current_result(DbResult* pResult) { - if (pResult == pCurrentResult_) - return; + if (pResult == pCurrentResult_) return; if (pCurrentResult_ != NULL) { - if (pResult != NULL) - warning("Cancelling previous query"); + if (pResult != NULL) warning("Cancelling previous query"); pCurrentResult_->close(); } @@ -165,8 +151,7 @@ void DbConnection::set_current_result(DbResult* pResult) { void DbConnection::reset_current_result(DbResult* pResult) { // FIXME: What to do if not current result is reset? - if (pResult != pCurrentResult_) - return; + if (pResult != pCurrentResult_) return; pCurrentResult_->close(); pCurrentResult_ = NULL; @@ -176,9 +161,7 @@ bool DbConnection::is_current_result(const DbResult* pResult) const { return pCurrentResult_ == pResult; } -bool DbConnection::has_query() { - return pCurrentResult_ != NULL; -} +bool DbConnection::has_query() { return pCurrentResult_ != NULL; } bool DbConnection::exec(const std::string& sql) { check_connection(); @@ -187,8 +170,7 @@ bool DbConnection::exec(const std::string& sql) { stop("Error executing query: %s", mysql_error(pConn_)); MYSQL_RES* res = mysql_store_result(pConn_); - if (res != NULL) - mysql_free_result(res); + if (res != NULL) mysql_free_result(res); autocommit(); @@ -218,9 +200,7 @@ void DbConnection::rollback() { transacting_ = false; } -bool DbConnection::is_transacting() const { - return transacting_; -} +bool DbConnection::is_transacting() const { return transacting_; } void DbConnection::autocommit() { if (!is_transacting() && get_conn()) { diff --git a/src/DbConnection.h b/src/DbConnection.h index 67558aef..2531fd3b 100644 --- a/src/DbConnection.h +++ b/src/DbConnection.h @@ -15,20 +15,24 @@ class DbConnection : boost::noncopyable { DbResult* pCurrentResult_; bool transacting_; -public: - + public: DbConnection(); ~DbConnection(); -public: - void - connect(const Nullable& host, const Nullable& user, const Nullable& password, - const Nullable& db, unsigned int port, const Nullable& unix_socket, - unsigned long client_flag, const Nullable& groups, const Nullable& default_file, - const Nullable& ssl_key, const Nullable& ssl_cert, - const Nullable& ssl_ca, const Nullable& ssl_capath, - const Nullable& ssl_cipher, - int timeout, bool reconnect); + public: + void connect(const Nullable& host, + const Nullable& user, + const Nullable& password, + const Nullable& db, unsigned int port, + const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, + const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, + bool reconnect); void disconnect(); bool is_valid(); void check_connection(); diff --git a/src/DbResult.cpp b/src/DbResult.cpp index b6a376fe..0f751124 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -1,15 +1,12 @@ -#include "pch.h" #include "DbResult.h" + #include "DbConnection.h" #include "DbResultImpl.h" - - +#include "pch.h" // Construction //////////////////////////////////////////////////////////////// -DbResult::DbResult(const DbConnectionPtr& pConn) : - pConn_(pConn) -{ +DbResult::DbResult(const DbConnectionPtr& pConn) : pConn_(pConn) { pConn_->check_connection(); // subclass constructor can throw, the destructor will remove the @@ -22,27 +19,19 @@ DbResult::~DbResult() { if (is_active()) { pConn_->reset_current_result(this); } - } catch (...) {} + } catch (...) { + } } - // Publics ///////////////////////////////////////////////////////////////////// -bool DbResult::complete() const { - return (impl == NULL) || impl->complete(); -} +bool DbResult::complete() const { return (impl == NULL) || impl->complete(); } -bool DbResult::is_active() const { - return pConn_->is_current_result(this); -} +bool DbResult::is_active() const { return pConn_->is_current_result(this); } -int DbResult::n_rows_fetched() { - return impl->n_rows_fetched(); -} +int DbResult::n_rows_fetched() { return impl->n_rows_fetched(); } -int DbResult::n_rows_affected() { - return impl->n_rows_affected(); -} +int DbResult::n_rows_affected() { return impl->n_rows_affected(); } void DbResult::bind(const List& params) { validate_params(params); @@ -50,8 +39,7 @@ void DbResult::bind(const List& params) { } List DbResult::fetch(const int n_max) { - if (!is_active()) - stop("Inactive result set"); + if (!is_active()) stop("Inactive result set"); return impl->fetch(n_max); } diff --git a/src/DbResult.h b/src/DbResult.h index f6d63717..dcc8e13c 100644 --- a/src/DbResult.h +++ b/src/DbResult.h @@ -2,12 +2,11 @@ #define __RDBI_DB_RESULT__ #include -#include #include +#include #include "DbResultImplDecl.h" - class DbConnection; typedef boost::shared_ptr DbConnectionPtr; @@ -16,16 +15,16 @@ typedef boost::shared_ptr DbConnectionPtr; class DbResult : boost::noncopyable { DbConnectionPtr pConn_; -protected: + protected: boost::scoped_ptr impl; -protected: + protected: DbResult(const DbConnectionPtr& pConn); -public: + public: ~DbResult(); -public: + public: void close(); bool complete() const; @@ -38,8 +37,8 @@ class DbResult : boost::noncopyable { List get_column_info(); -private: + private: void validate_params(const List& params) const; }; -#endif // __RDBI_DB_RESULT__ +#endif // __RDBI_DB_RESULT__ diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index 63ffc93d..b360f100 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -1,17 +1,13 @@ -#include "pch.h" -#include #include "MariaBinding.h" + +#include + #include "integer64.h" +#include "pch.h" -MariaBinding::MariaBinding() : - statement(NULL), - p(0), - i(0), - n_rows(0) { -} +MariaBinding::MariaBinding() : statement(NULL), p(0), i(0), n_rows(0) {} -MariaBinding::~MariaBinding() { -} +MariaBinding::~MariaBinding() {} void MariaBinding::setup(MYSQL_STMT* statement_) { LOG_VERBOSE; @@ -52,33 +48,33 @@ void MariaBinding::init_binding(const List& params_) { } switch (type) { - case MY_LGL: - binding_update(j, MYSQL_TYPE_TINY, 1); - break; - case MY_INT32: - binding_update(j, MYSQL_TYPE_LONG, 4); - break; - case MY_DBL: - binding_update(j, MYSQL_TYPE_DOUBLE, 8); - break; - case MY_DATE: - binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); - break; - case MY_TIME: - binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); - break; - case MY_STR: - binding_update(j, MYSQL_TYPE_STRING, 0); - break; - case MY_RAW: - binding_update(j, MYSQL_TYPE_BLOB, 0); - break; - case MY_INT64: - binding_update(j, MYSQL_TYPE_LONGLONG, 0); - break; + case MY_LGL: + binding_update(j, MYSQL_TYPE_TINY, 1); + break; + case MY_INT32: + binding_update(j, MYSQL_TYPE_LONG, 4); + break; + case MY_DBL: + binding_update(j, MYSQL_TYPE_DOUBLE, 8); + break; + case MY_DATE: + binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); + break; + case MY_TIME: + binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); + break; + case MY_STR: + binding_update(j, MYSQL_TYPE_STRING, 0); + break; + case MY_RAW: + binding_update(j, MYSQL_TYPE_BLOB, 0); + break; + case MY_INT64: + binding_update(j, MYSQL_TYPE_LONGLONG, 0); + break; } } } @@ -95,39 +91,38 @@ bool MariaBinding::bind_next_row() { RObject col(params[j]); switch (types[j]) { - case MY_LGL: - if (LOGICAL(col)[i] == NA_LOGICAL) { - missing = true; + case MY_LGL: + if (LOGICAL(col)[i] == NA_LOGICAL) { + missing = true; + break; + } + bindings[j].buffer = &LOGICAL(col)[i]; break; - } - bindings[j].buffer = &LOGICAL(col)[i]; - break; - case MY_INT32: - if (INTEGER(col)[i] == NA_INTEGER) { - missing = true; + case MY_INT32: + if (INTEGER(col)[i] == NA_INTEGER) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER(col)[i]; break; - } - bindings[j].buffer = &INTEGER(col)[i]; - break; - case MY_DBL: - if (ISNA(REAL(col)[i])) { - missing = true; + case MY_DBL: + if (ISNA(REAL(col)[i])) { + missing = true; + break; + } + bindings[j].buffer = &REAL(col)[i]; break; - } - bindings[j].buffer = &REAL(col)[i]; - break; - case MY_STR: - if (STRING_ELT(col, i) == NA_STRING) { - missing = true; + case MY_STR: + if (STRING_ELT(col, i) == NA_STRING) { + missing = true; + break; + } else { + SEXP string = STRING_ELT(col, i); + bindings[j].buffer = const_cast(CHAR(string)); + bindings[j].buffer_length = Rf_length(string); + } break; - } else { - SEXP string = STRING_ELT(col, i); - bindings[j].buffer = const_cast(CHAR(string)); - bindings[j].buffer_length = Rf_length(string); - } - break; - case MY_RAW: - { + case MY_RAW: { SEXP raw = VECTOR_ELT(col, i); if (Rf_isNull(raw)) { missing = true; @@ -137,45 +132,45 @@ bool MariaBinding::bind_next_row() { } break; } - case MY_DATE: - case MY_DATE_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - } else { - double val = REAL(col)[i]; - LOG_VERBOSE << val; - if (types[j] == MY_DATE) { - set_date_buffer(j, static_cast(::floor(val))); - clear_time_buffer(j); + case MY_DATE: + case MY_DATE_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; } else { - double days = ::floor(val / 86400.0); - set_date_buffer(j, static_cast(days)); - set_time_buffer(j, val - days * 86400.0); + double val = REAL(col)[i]; + LOG_VERBOSE << val; + if (types[j] == MY_DATE) { + set_date_buffer(j, static_cast(::floor(val))); + clear_time_buffer(j); + } else { + double days = ::floor(val / 86400.0); + set_date_buffer(j, static_cast(days)); + set_time_buffer(j, val - days * 86400.0); + } + LOG_VERBOSE; + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; } - LOG_VERBOSE; - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; break; - } else { - double val = REAL(col)[i]; - clear_date_buffer(j); - set_time_buffer(j, val); - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_INT64: - if (INTEGER64(col)[i] == NA_INTEGER64) { - missing = true; + case MY_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + break; + } else { + double val = REAL(col)[i]; + clear_date_buffer(j); + set_time_buffer(j, val); + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_INT64: + if (INTEGER64(col)[i] == NA_INTEGER64) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER64(col)[i]; break; - } - bindings[j].buffer = &INTEGER64(col)[i]; - break; } is_null[j] = missing; } @@ -209,15 +204,17 @@ void MariaBinding::set_date_buffer(int j, const int date) { // https://howardhinnant.github.io/date_algorithms.html#civil_from_days const int date_0 = date + 719468; const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; - const unsigned doe = static_cast(date_0 - era * 146097); // [0, 146096] + const unsigned doe = + static_cast(date_0 - era * 146097); // [0, 146096] LOG_VERBOSE << doe; - const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] + const unsigned yoe = + (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] LOG_VERBOSE << yoe; const int y = static_cast(yoe) + era * 400; - const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] - const unsigned mp = (5*doy + 2)/153; // [0, 11] - const unsigned d = doy - (153*mp+2)/5 + 1; // [1, 31] - const unsigned m = mp < 10 ? mp+3 : mp-9; // [1, 12] + const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] + const unsigned mp = (5 * doy + 2) / 153; // [0, 11] + const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] + const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] const unsigned yr = y + (m <= 2); // gmtime() fails for dates < 1970 on Windows @@ -258,6 +255,7 @@ void MariaBinding::set_time_buffer(int j, double time) { time_buffers[j].hour = static_cast(hours); time_buffers[j].minute = static_cast(minutes); time_buffers[j].second = static_cast(seconds); - time_buffers[j].second_part = static_cast(frac_seconds * 1000000.0); + time_buffers[j].second_part = + static_cast(frac_seconds * 1000000.0); time_buffers[j].neg = neg; } diff --git a/src/MariaBinding.h b/src/MariaBinding.h index fb9bc8c7..9a7173ed 100644 --- a/src/MariaBinding.h +++ b/src/MariaBinding.h @@ -3,6 +3,7 @@ #include #include + #include "MariaTypes.h" class MariaBinding : public boost::noncopyable { @@ -16,17 +17,17 @@ class MariaBinding : public boost::noncopyable { std::vector types; std::vector time_buffers; -public: + public: MariaBinding(); ~MariaBinding(); -public: + public: void setup(MYSQL_STMT* statement_); void init_binding(const List& params); bool bind_next_row(); -private: + private: void binding_update(int j, enum_field_types type, int size); void clear_date_buffer(int j); diff --git a/src/MariaResult.cpp b/src/MariaResult.cpp index 64e8d0fa..f3031f80 100644 --- a/src/MariaResult.cpp +++ b/src/MariaResult.cpp @@ -1,19 +1,19 @@ -#include "pch.h" #include "MariaResult.h" + #include "MariaResultPrep.h" #include "MariaResultSimple.h" - +#include "pch.h" // Construction //////////////////////////////////////////////////////////////// -MariaResult::MariaResult(const DbConnectionPtr& pConn, const std::string& sql, bool is_statement) : - DbResult(pConn) -{ - boost::scoped_ptr res(new MariaResultPrep(pConn, is_statement)); +MariaResult::MariaResult(const DbConnectionPtr& pConn, const std::string& sql, + bool is_statement) + : DbResult(pConn) { + boost::scoped_ptr res( + new MariaResultPrep(pConn, is_statement)); try { res->send_query(sql); - } - catch (const MariaResultPrep::UnsupportedPS& e) { + } catch (const MariaResultPrep::UnsupportedPS& e) { res.reset(NULL); // is_statement info might be worthwhile to pass to simple queries as well res.reset(new MariaResultSimple(pConn, is_statement)); @@ -23,7 +23,9 @@ MariaResult::MariaResult(const DbConnectionPtr& pConn, const std::string& sql, b res.swap(impl); } -DbResult* MariaResult::create_and_send_query(const DbConnectionPtr& con, const std::string& sql, bool is_statement) { +DbResult* MariaResult::create_and_send_query(const DbConnectionPtr& con, + const std::string& sql, + bool is_statement) { return new MariaResult(con, sql, is_statement); } diff --git a/src/MariaResult.h b/src/MariaResult.h index ad24d73e..3e4f5950 100644 --- a/src/MariaResult.h +++ b/src/MariaResult.h @@ -3,18 +3,20 @@ #include "DbResult.h" - // MariaResult ----------------------------------------------------------------- class MariaResult : public DbResult { -protected: - MariaResult(const DbConnectionPtr& pConn, const std::string& sql, bool is_statement); + protected: + MariaResult(const DbConnectionPtr& pConn, const std::string& sql, + bool is_statement); -public: - static DbResult* create_and_send_query(const DbConnectionPtr& con, const std::string& sql, bool is_statement); + public: + static DbResult* create_and_send_query(const DbConnectionPtr& con, + const std::string& sql, + bool is_statement); -public: + public: void close(); }; -#endif // __RMARIADB_MARIA_RESULT__ +#endif // __RMARIADB_MARIA_RESULT__ diff --git a/src/MariaResultImpl.cpp b/src/MariaResultImpl.cpp index e260880f..739e4eb5 100644 --- a/src/MariaResultImpl.cpp +++ b/src/MariaResultImpl.cpp @@ -1,8 +1,7 @@ -#include "pch.h" #include "MariaResultImpl.h" -MariaResultImpl::MariaResultImpl() { -} +#include "pch.h" + +MariaResultImpl::MariaResultImpl() {} -MariaResultImpl::~MariaResultImpl() { -} +MariaResultImpl::~MariaResultImpl() {} diff --git a/src/MariaResultImpl.h b/src/MariaResultImpl.h index 58120d26..8eb2acd4 100644 --- a/src/MariaResultImpl.h +++ b/src/MariaResultImpl.h @@ -2,11 +2,11 @@ #define RMARIADB_MARIARESULTIMPL_H class MariaResultImpl { -public: + public: MariaResultImpl(); virtual ~MariaResultImpl(); -public: + public: virtual void send_query(const std::string& sql) = 0; virtual void close() = 0; @@ -21,4 +21,4 @@ class MariaResultImpl { virtual bool complete() const = 0; }; -#endif //RMARIADB_MARIARESULTIMPL_H +#endif // RMARIADB_MARIARESULTIMPL_H diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index 3bc63cdd..93466c86 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -1,30 +1,28 @@ -#include "pch.h" - #include "MariaResultPrep.h" -#include "DbConnection.h" + #include + +#include "DbConnection.h" #include "MariaResult.h" +#include "pch.h" -MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement) : - pConn_(pConn), - pStatement_(NULL), - pSpec_(NULL), - rowsAffected_(0), - rowsFetched_(0), - nCols_(0), - nParams_(0), - bound_(false), - complete_(false), - is_statement_(is_statement) -{ +MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, + bool is_statement) + : pConn_(pConn), + pStatement_(NULL), + pSpec_(NULL), + rowsAffected_(0), + rowsFetched_(0), + nCols_(0), + nParams_(0), + bound_(false), + complete_(false), + is_statement_(is_statement) { pStatement_ = mysql_stmt_init(pConn_->get_conn()); - if (pStatement_ == NULL) - stop("Out of memory"); + if (pStatement_ == NULL) stop("Out of memory"); } -MariaResultPrep::~MariaResultPrep() { - MariaResultPrep::close(); -} +MariaResultPrep::~MariaResultPrep() { MariaResultPrep::close(); } void MariaResultPrep::send_query(const std::string& sql) { LOG_DEBUG << sql; @@ -101,8 +99,7 @@ void MariaResultPrep::bind(const List& params) { if (has_result()) { complete_ = true; - } - else { + } else { while (bindingInput_.bind_next_row()) { execute(); } @@ -121,9 +118,7 @@ List MariaResultPrep::get_column_info() { return List::create(_["name"] = names, _["type"] = types); } -bool MariaResultPrep::has_result() const { - return pSpec_ != NULL; -} +bool MariaResultPrep::has_result() const { return pSpec_ != NULL; } bool MariaResultPrep::step() { LOG_VERBOSE; @@ -152,41 +147,40 @@ bool MariaResultPrep::fetch_row() { LOG_VERBOSE << result; switch (result) { - // We expect truncation whenever there's a string or blob - case MYSQL_DATA_TRUNCATED: - case 0: - return true; - case 1: - throw_error(); - case MYSQL_NO_DATA: - complete_ = true; - return false; + // We expect truncation whenever there's a string or blob + case MYSQL_DATA_TRUNCATED: + case 0: + return true; + case 1: + throw_error(); + case MYSQL_NO_DATA: + complete_ = true; + return false; } return false; } List MariaResultPrep::fetch(int n_max) { - if (!bound_) - stop("Query needs to be bound before fetching"); + if (!bound_) stop("Query needs to be bound before fetching"); if (!has_result()) { if (names_.size() == 0) { - warning("Use dbExecute() instead of dbGetQuery() for statements, and also avoid dbFetch()"); + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and also " + "avoid dbFetch()"); } return df_create(types_, names_, 0); } int n = (n_max < 0) ? 100 : n_max; List out = df_create(types_, names_, n); - if (n == 0) - return out; + if (n == 0) return out; int i = 0; for (;;) { if (i >= n && n_max > 0) break; - if (!step()) - break; + if (!step()) break; if (i >= n) { n *= 2; @@ -199,8 +193,7 @@ List MariaResultPrep::fetch(int n_max) { } ++i; - if (i % 1024 == 0) - checkUserInterrupt(); + if (i % 1024 == 0) checkUserInterrupt(); } // Trim back to what we actually used @@ -227,17 +220,12 @@ int MariaResultPrep::n_rows_fetched() { bool MariaResultPrep::complete() const { if (!bound_) return FALSE; - return - !has_result() || // query doesn't have results - complete_; // we've fetched all available results + return !has_result() || // query doesn't have results + complete_; // we've fetched all available results } void MariaResultPrep::throw_error() { - stop( - "%s [%i]", - mysql_stmt_error(pStatement_), - mysql_stmt_errno(pStatement_) - ); + stop("%s [%i]", mysql_stmt_error(pStatement_), mysql_stmt_errno(pStatement_)); } void MariaResultPrep::cache_metadata() { @@ -251,9 +239,11 @@ void MariaResultPrep::cache_metadata() { bool binary = fields[i].charsetnr == 63; bool length1 = fields[i].length == 1; - MariaFieldType type = variable_type_from_field_type(fields[i].type, binary, length1); + MariaFieldType type = + variable_type_from_field_type(fields[i].type, binary, length1); types_.push_back(type); - LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type << ", " << binary << ") => " << type_name(type); + LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type + << ", " << binary << ") => " << type_name(type); } } diff --git a/src/MariaResultPrep.h b/src/MariaResultPrep.h index d696c239..9c55af9c 100644 --- a/src/MariaResultPrep.h +++ b/src/MariaResultPrep.h @@ -29,11 +29,11 @@ class MariaResultPrep : boost::noncopyable, public MariaResultImpl { MariaBinding bindingInput_; MariaRow bindingOutput_; -public: + public: MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); ~MariaResultPrep(); -public: + public: virtual void send_query(const std::string& sql); virtual void close(); @@ -47,10 +47,10 @@ class MariaResultPrep : boost::noncopyable, public MariaResultImpl { virtual int n_rows_fetched(); virtual bool complete() const; -public: + public: class UnsupportedPS : public std::exception {}; -private: + private: void execute(); bool has_result() const; @@ -58,7 +58,7 @@ class MariaResultPrep : boost::noncopyable, public MariaResultImpl { bool fetch_row(); void NORET throw_error(); -private: + private: void cache_metadata(); }; diff --git a/src/MariaResultSimple.cpp b/src/MariaResultSimple.cpp index 748a4339..a5539f5f 100644 --- a/src/MariaResultSimple.cpp +++ b/src/MariaResultSimple.cpp @@ -1,17 +1,15 @@ -#include "pch.h" - #include "MariaResultSimple.h" + #include "DbConnection.h" +#include "pch.h" -MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement) : - pConn_(pConn) -{ +MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, + bool is_statement) + : pConn_(pConn) { (void)is_statement; } -MariaResultSimple::~MariaResultSimple() { - MariaResultSimple::close(); -} +MariaResultSimple::~MariaResultSimple() { MariaResultSimple::close(); } void MariaResultSimple::send_query(const std::string& sql) { LOG_DEBUG << sql; @@ -19,14 +17,14 @@ void MariaResultSimple::send_query(const std::string& sql) { exec(sql); } -void MariaResultSimple::close() { - LOG_VERBOSE; -} +void MariaResultSimple::close() { LOG_VERBOSE; } void MariaResultSimple::bind(const List& /*params*/) { LOG_VERBOSE; - stop("This query is not supported by the prepared statement protocol, no parameters can be bound."); + stop( + "This query is not supported by the prepared statement protocol, no " + "parameters can be bound."); } List MariaResultSimple::get_column_info() { @@ -38,22 +36,17 @@ List MariaResultSimple::get_column_info() { List MariaResultSimple::fetch(int /*n_max*/) { LOG_VERBOSE; - warning("Use dbExecute() instead of dbGetQuery() for statements, and also avoid dbFetch()"); - return df_create(std::vector(), std::vector(), 0); + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and also avoid " + "dbFetch()"); + return df_create(std::vector(), std::vector(), + 0); } -int MariaResultSimple::n_rows_affected() { - return 0; -} +int MariaResultSimple::n_rows_affected() { return 0; } -int MariaResultSimple::n_rows_fetched() { - return 0; -} +int MariaResultSimple::n_rows_fetched() { return 0; } -bool MariaResultSimple::complete() const { - return true; -} +bool MariaResultSimple::complete() const { return true; } -void MariaResultSimple::exec(const std::string& sql) { - pConn_->exec(sql); -} +void MariaResultSimple::exec(const std::string& sql) { pConn_->exec(sql); } diff --git a/src/MariaResultSimple.h b/src/MariaResultSimple.h index e586e069..329e62d7 100644 --- a/src/MariaResultSimple.h +++ b/src/MariaResultSimple.h @@ -2,8 +2,9 @@ #define __RMARIADB_MARIA_RESULT_SIMPLE__ #include -#include "MariaBinding.h" + #include "DbResult.h" +#include "MariaBinding.h" #include "MariaResultImpl.h" #include "MariaRow.h" #include "MariaTypes.h" @@ -15,11 +16,11 @@ typedef boost::shared_ptr DbConnectionPtr; class MariaResultSimple : boost::noncopyable, public MariaResultImpl { DbConnectionPtr pConn_; -public: + public: MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); ~MariaResultSimple(); -public: + public: virtual void send_query(const std::string& sql); virtual void close(); @@ -33,7 +34,7 @@ class MariaResultSimple : boost::noncopyable, public MariaResultImpl { virtual int n_rows_fetched(); virtual bool complete() const; -private: + private: void exec(const std::string& sql); }; diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index fa9301a3..925ec11d 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -1,21 +1,16 @@ -#include "pch.h" - #include "MariaRow.h" + #include "MariaTypes.h" #include "MariaUtils.h" #include "integer64.h" +#include "pch.h" +MariaRow::MariaRow() : pStatement_(NULL), n_(0) {} -MariaRow::MariaRow() : - pStatement_(NULL), - n_(0) -{ -} +MariaRow::~MariaRow() {} -MariaRow::~MariaRow() { -} - -void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& types) { +void MariaRow::setup(MYSQL_STMT* pStatement, + const std::vector& types) { LOG_VERBOSE; pStatement_ = pStatement; @@ -33,47 +28,47 @@ void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html switch (types_[j]) { - case MY_INT32: - bindings_[j].buffer_type = MYSQL_TYPE_LONG; - buffers_[j].resize(4); - break; - case MY_INT64: - bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; - buffers_[j].resize(8); - break; - case MY_DBL: - bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; - buffers_[j].resize(8); - break; - case MY_DATE: - bindings_[j].buffer_type = MYSQL_TYPE_DATE; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_TIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_STR: - bindings_[j].buffer_type = MYSQL_TYPE_STRING; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_RAW: - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_LGL: - // BIT(1) is bound to logical, in absence of dedicated type - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(4); - break; + case MY_INT32: + bindings_[j].buffer_type = MYSQL_TYPE_LONG; + buffers_[j].resize(4); + break; + case MY_INT64: + bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; + buffers_[j].resize(8); + break; + case MY_DBL: + bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; + buffers_[j].resize(8); + break; + case MY_DATE: + bindings_[j].buffer_type = MYSQL_TYPE_DATE; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_TIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_STR: + bindings_[j].buffer_type = MYSQL_TYPE_STRING; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_RAW: + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_LGL: + // BIT(1) is bound to logical, in absence of dedicated type + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(4); + break; } lengths_[j] = buffers_[j].size(); @@ -110,9 +105,7 @@ void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& } } -bool MariaRow::is_null(int j) { - return nulls_[j] == 1; -} +bool MariaRow::is_null(int j) { return nulls_[j] == 1; } int MariaRow::value_bool(int j) { if (is_null(j)) { @@ -123,33 +116,30 @@ int MariaRow::value_bool(int j) { } int MariaRow::value_int(int j) { - return is_null(j) ? NA_INTEGER : *((int*) &buffers_[j][0]); + return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); } int64_t MariaRow::value_int64(int j) { - return is_null(j) ? NA_INTEGER64 : *((int64_t*) &buffers_[j][0]); + return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); } double MariaRow::value_double(int j) { - return is_null(j) ? NA_REAL : *((double*) &buffers_[j][0]); + return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); } SEXP MariaRow::value_string(int j) { - if (is_null(j)) - return NA_STRING; + if (is_null(j)) return NA_STRING; fetch_buffer(j); int len = static_cast(buffers_[j].size()); - if (len == 0) - return R_BlankString; + if (len == 0) return R_BlankString; const char* val = reinterpret_cast(&buffers_[j][0]); return Rf_mkCharLenCE(val, len, CE_UTF8); } SEXP MariaRow::value_raw(int j) { - if (is_null(j)) - return R_NilValue; + if (is_null(j)) return R_NilValue; fetch_buffer(j); SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); @@ -159,27 +149,24 @@ SEXP MariaRow::value_raw(int j) { } double MariaRow::value_date_time(int j) { - if (is_null(j)) - return NA_REAL; + if (is_null(j)) return NA_REAL; - MYSQL_TIME* mytime = (MYSQL_TIME*) &buffers_[j][0]; + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = - static_cast(days) * 86400.0 + - static_cast(mytime->hour) * (60.0 * 60) + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; + double date_time = static_cast(days) * 86400.0 + + static_cast(mytime->hour) * (60.0 * 60) + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; LOG_VERBOSE << date_time; return date_time; } double MariaRow::value_date(int j) { - if (is_null(j)) - return NA_REAL; + if (is_null(j)) return NA_REAL; - MYSQL_TIME* mytime = (MYSQL_TIME*) &buffers_[j][0]; + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; const int days = days_from_civil(mytime->year, mytime->month, mytime->day); double date_time = static_cast(days); @@ -188,10 +175,9 @@ double MariaRow::value_date(int j) { } double MariaRow::value_time(int j) { - if (is_null(j)) - return NA_REAL; + if (is_null(j)) return NA_REAL; - MYSQL_TIME* mytime = (MYSQL_TIME*) &buffers_[j][0]; + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; return static_cast(mytime->hour) * 3600.0 + static_cast(mytime->minute) * 60.0 + static_cast(mytime->second) + @@ -200,33 +186,33 @@ double MariaRow::value_time(int j) { void MariaRow::set_list_value(SEXP x, int i, int j) { switch (types_[j]) { - case MY_INT32: - INTEGER(x)[i] = value_int(j); - break; - case MY_INT64: - INTEGER64(x)[i] = value_int64(j); - break; - case MY_DBL: - REAL(x)[i] = value_double(j); - break; - case MY_DATE: - REAL(x)[i] = value_date(j); - break; - case MY_DATE_TIME: - REAL(x)[i] = value_date_time(j); - break; - case MY_TIME: - REAL(x)[i] = value_time(j); - break; - case MY_STR: - SET_STRING_ELT(x, i, value_string(j)); - break; - case MY_RAW: - SET_VECTOR_ELT(x, i, value_raw(j)); - break; - case MY_LGL: - LOGICAL(x)[i] = value_bool(j); - break; + case MY_INT32: + INTEGER(x)[i] = value_int(j); + break; + case MY_INT64: + INTEGER64(x)[i] = value_int64(j); + break; + case MY_DBL: + REAL(x)[i] = value_double(j); + break; + case MY_DATE: + REAL(x)[i] = value_date(j); + break; + case MY_DATE_TIME: + REAL(x)[i] = value_date_time(j); + break; + case MY_TIME: + REAL(x)[i] = value_time(j); + break; + case MY_STR: + SET_STRING_ELT(x, i, value_string(j)); + break; + case MY_RAW: + SET_VECTOR_ELT(x, i, value_raw(j)); + break; + case MY_LGL: + LOGICAL(x)[i] = value_bool(j); + break; } } @@ -235,10 +221,9 @@ void MariaRow::fetch_buffer(int j) { LOG_VERBOSE << length; buffers_[j].resize(length); - if (length == 0) - return; + if (length == 0) return; - bindings_[j].buffer = &buffers_[j][0]; // might have moved + bindings_[j].buffer = &buffers_[j][0]; // might have moved bindings_[j].buffer_length = length; LOG_VERBOSE << bindings_[j].buffer_length; diff --git a/src/MariaRow.h b/src/MariaRow.h index 476ed4d5..d2a31e9b 100644 --- a/src/MariaRow.h +++ b/src/MariaRow.h @@ -1,8 +1,8 @@ #ifndef __RMARIADB_MARIA_ROW__ #define __RMARIADB_MARIA_ROW__ -#include #include +#include #include #include "MariaTypes.h" @@ -18,15 +18,15 @@ class MariaRow : public boost::noncopyable { std::vector lengths_; boost::container::vector nulls_, errors_; -public: + public: MariaRow(); ~MariaRow(); -public: + public: void setup(MYSQL_STMT* pStatement, const std::vector& types); void set_list_value(SEXP x, int i, int j); -private: + private: // Value accessors ----------------------------------------------------------- bool is_null(int j); diff --git a/src/MariaTypes.cpp b/src/MariaTypes.cpp index dd0df652..be60c8f0 100644 --- a/src/MariaTypes.cpp +++ b/src/MariaTypes.cpp @@ -1,104 +1,106 @@ -#include "pch.h" #include "MariaTypes.h" + #include "integer64.h" +#include "pch.h" bool all_raw(SEXP x); -MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, bool length1) { +MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, + bool length1) { switch (type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_YEAR: - return MY_INT32; + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_YEAR: + return MY_INT32; - case MYSQL_TYPE_LONGLONG: - return MY_INT64; + case MYSQL_TYPE_LONGLONG: + return MY_INT64; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - return MY_DBL; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - return MY_DATE_TIME; - case MYSQL_TYPE_DATE: - return MY_DATE; - case MYSQL_TYPE_TIME: - return MY_TIME; - case MYSQL_TYPE_BIT: - if (length1) { - return MY_LGL; - } - // fallthrough - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_SET: - return MY_STR; - case MYSQL_TYPE_GEOMETRY: - return MY_RAW; - case MYSQL_TYPE_NULL: - return MY_INT32; - default: - throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + return MY_DBL; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_NEWDATE: + return MY_DATE_TIME; + case MYSQL_TYPE_DATE: + return MY_DATE; + case MYSQL_TYPE_TIME: + return MY_TIME; + case MYSQL_TYPE_BIT: + if (length1) { + return MY_LGL; + } + // fallthrough + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_SET: + return MY_STR; + case MYSQL_TYPE_GEOMETRY: + return MY_RAW; + case MYSQL_TYPE_NULL: + return MY_INT32; + default: + throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); } } std::string type_name(MariaFieldType type) { switch (type) { - case MY_INT32: - return "integer"; - case MY_INT64: - return "integer64"; - case MY_DBL: - return "double"; - case MY_STR: - return "string"; - case MY_DATE: - return "Date"; - case MY_DATE_TIME: - return "POSIXct"; - case MY_TIME: - return "hms"; - case MY_RAW: - return "raw"; - case MY_LGL: - return "logical"; + case MY_INT32: + return "integer"; + case MY_INT64: + return "integer64"; + case MY_DBL: + return "double"; + case MY_STR: + return "string"; + case MY_DATE: + return "Date"; + case MY_DATE_TIME: + return "POSIXct"; + case MY_TIME: + return "hms"; + case MY_RAW: + return "raw"; + case MY_LGL: + return "logical"; } throw std::runtime_error("Invalid typeName"); } SEXPTYPE type_sexp(MariaFieldType type) { switch (type) { - case MY_INT32: - return INTSXP; - case MY_INT64: - return INT64SXP; - case MY_DBL: - return REALSXP; - case MY_STR: - return STRSXP; - case MY_DATE: - return REALSXP; - case MY_DATE_TIME: - return REALSXP; - case MY_TIME: - return REALSXP; - case MY_RAW: - return VECSXP; - case MY_LGL: - return LGLSXP; + case MY_INT32: + return INTSXP; + case MY_INT64: + return INT64SXP; + case MY_DBL: + return REALSXP; + case MY_STR: + return STRSXP; + case MY_DATE: + return REALSXP; + case MY_DATE_TIME: + return REALSXP; + case MY_TIME: + return REALSXP; + case MY_RAW: + return VECSXP; + case MY_LGL: + return LGLSXP; } throw std::runtime_error("Invalid typeSEXP"); } @@ -106,8 +108,7 @@ SEXPTYPE type_sexp(MariaFieldType type) { std::string r_class(RObject x) { RObject klass_(x.attr("class")); std::string klass; - if (klass_ == R_NilValue) - return ""; + if (klass_ == R_NilValue) return ""; CharacterVector klassv = as(klass_); return std::string(klassv[klassv.length() - 1]); @@ -117,22 +118,22 @@ MariaFieldType variable_type_from_object(const RObject& type) { std::string klass = r_class(type); switch (TYPEOF(type)) { - case LGLSXP: - return MY_LGL; - case INTSXP: - return MY_INT32; - case REALSXP: - if (klass == "Date") return MY_DATE; - if (klass == "POSIXt") return MY_DATE_TIME; - if (klass == "difftime") return MY_TIME; - if (klass == "integer64") return MY_INT64; - return MY_DBL; - case STRSXP: - return MY_STR; - case VECSXP: - if (klass == "blob") return MY_RAW; - if (all_raw(type)) return MY_RAW; - break; + case LGLSXP: + return MY_LGL; + case INTSXP: + return MY_INT32; + case REALSXP: + if (klass == "Date") return MY_DATE; + if (klass == "POSIXt") return MY_DATE_TIME; + if (klass == "difftime") return MY_TIME; + if (klass == "integer64") return MY_INT64; + return MY_DBL; + case STRSXP: + return MY_STR; + case VECSXP: + if (klass == "blob") return MY_RAW; + if (all_raw(type)) return MY_RAW; + break; } stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); @@ -143,12 +144,12 @@ bool all_raw(SEXP x) { List xx(x); for (R_xlen_t i = 0; i < xx.length(); ++i) { switch (TYPEOF(xx[i])) { - case RAWSXP: - case NILSXP: - break; + case RAWSXP: + case NILSXP: + break; - default: - return false; + default: + return false; } } return true; diff --git a/src/MariaTypes.h b/src/MariaTypes.h index c1b8d5a1..df681f7f 100644 --- a/src/MariaTypes.h +++ b/src/MariaTypes.h @@ -3,22 +3,22 @@ enum MariaFieldType { MY_INT32, - MY_INT64, // output only + MY_INT64, // output only MY_DBL, MY_STR, MY_DATE, MY_DATE_TIME, MY_TIME, MY_RAW, - MY_LGL // for BIT(1) + MY_LGL // for BIT(1) }; -MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, bool length1); +MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, + bool length1); std::string type_name(MariaFieldType type); SEXPTYPE type_sexp(MariaFieldType type); std::string r_class(RObject x); MariaFieldType variable_type_from_object(const RObject& type); - #endif diff --git a/src/RMariaDB_types.h b/src/RMariaDB_types.h index 5ab1665a..449f80be 100644 --- a/src/RMariaDB_types.h +++ b/src/RMariaDB_types.h @@ -9,12 +9,12 @@ namespace Rcpp { -template<> +template <> DbConnection* as(SEXP x); -template<> +template <> DbResult* as(SEXP x); -} +} // namespace Rcpp #endif diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index c12a410d..d772fcae 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -1,294 +1,333 @@ // Generated by using Rcpp::compileAttributes() -> do not edit by hand // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 -#include "RMariaDB_types.h" #include +#include "RMariaDB_types.h" + using namespace Rcpp; #ifdef RCPP_USE_GLOBAL_ROSTREAM -Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); +Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); #endif // connection_create -XPtr connection_create(const Nullable& host, const Nullable& user, const Nullable& password, const Nullable& db, unsigned int port, const Nullable& unix_socket, unsigned long client_flag, const Nullable& groups, const Nullable& default_file, const Nullable& ssl_key, const Nullable& ssl_cert, const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect); -RcppExport SEXP _RMariaDB_connection_create(SEXP hostSEXP, SEXP userSEXP, SEXP passwordSEXP, SEXP dbSEXP, SEXP portSEXP, SEXP unix_socketSEXP, SEXP client_flagSEXP, SEXP groupsSEXP, SEXP default_fileSEXP, SEXP ssl_keySEXP, SEXP ssl_certSEXP, SEXP ssl_caSEXP, SEXP ssl_capathSEXP, SEXP ssl_cipherSEXP, SEXP timeoutSEXP, SEXP reconnectSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const Nullable& >::type host(hostSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type user(userSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type password(passwordSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type db(dbSEXP); - Rcpp::traits::input_parameter< unsigned int >::type port(portSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type unix_socket(unix_socketSEXP); - Rcpp::traits::input_parameter< unsigned long >::type client_flag(client_flagSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type groups(groupsSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type default_file(default_fileSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type ssl_key(ssl_keySEXP); - Rcpp::traits::input_parameter< const Nullable& >::type ssl_cert(ssl_certSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type ssl_ca(ssl_caSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type ssl_capath(ssl_capathSEXP); - Rcpp::traits::input_parameter< const Nullable& >::type ssl_cipher(ssl_cipherSEXP); - Rcpp::traits::input_parameter< int >::type timeout(timeoutSEXP); - Rcpp::traits::input_parameter< bool >::type reconnect(reconnectSEXP); - rcpp_result_gen = Rcpp::wrap(connection_create(host, user, password, db, port, unix_socket, client_flag, groups, default_file, ssl_key, ssl_cert, ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); - return rcpp_result_gen; -END_RCPP +XPtr connection_create( + const Nullable& host, const Nullable& user, + const Nullable& password, const Nullable& db, + unsigned int port, const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, bool reconnect); +RcppExport SEXP _RMariaDB_connection_create( + SEXP hostSEXP, SEXP userSEXP, SEXP passwordSEXP, SEXP dbSEXP, SEXP portSEXP, + SEXP unix_socketSEXP, SEXP client_flagSEXP, SEXP groupsSEXP, + SEXP default_fileSEXP, SEXP ssl_keySEXP, SEXP ssl_certSEXP, SEXP ssl_caSEXP, + SEXP ssl_capathSEXP, SEXP ssl_cipherSEXP, SEXP timeoutSEXP, + SEXP reconnectSEXP) { + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter&>::type host( + hostSEXP); + Rcpp::traits::input_parameter&>::type user( + userSEXP); + Rcpp::traits::input_parameter&>::type password( + passwordSEXP); + Rcpp::traits::input_parameter&>::type db(dbSEXP); + Rcpp::traits::input_parameter::type port(portSEXP); + Rcpp::traits::input_parameter&>::type unix_socket( + unix_socketSEXP); + Rcpp::traits::input_parameter::type client_flag( + client_flagSEXP); + Rcpp::traits::input_parameter&>::type groups( + groupsSEXP); + Rcpp::traits::input_parameter&>::type + default_file(default_fileSEXP); + Rcpp::traits::input_parameter&>::type ssl_key( + ssl_keySEXP); + Rcpp::traits::input_parameter&>::type ssl_cert( + ssl_certSEXP); + Rcpp::traits::input_parameter&>::type ssl_ca( + ssl_caSEXP); + Rcpp::traits::input_parameter&>::type ssl_capath( + ssl_capathSEXP); + Rcpp::traits::input_parameter&>::type ssl_cipher( + ssl_cipherSEXP); + Rcpp::traits::input_parameter::type timeout(timeoutSEXP); + Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); + rcpp_result_gen = Rcpp::wrap( + connection_create(host, user, password, db, port, unix_socket, + client_flag, groups, default_file, ssl_key, ssl_cert, + ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); + return rcpp_result_gen; + END_RCPP } // connection_valid bool connection_valid(XPtr con_); RcppExport SEXP _RMariaDB_connection_valid(SEXP con_SEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type con_(con_SEXP); - rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); + return rcpp_result_gen; + END_RCPP } // connection_release void connection_release(XPtr con_); RcppExport SEXP _RMariaDB_connection_release(SEXP con_SEXP) { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type con_(con_SEXP); - connection_release(con_); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + connection_release(con_); + return R_NilValue; + END_RCPP } // connection_info List connection_info(DbConnection* con); RcppExport SEXP _RMariaDB_connection_info(SEXP conSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbConnection* >::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_info(con)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_info(con)); + return rcpp_result_gen; + END_RCPP } // connection_quote_string CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs); RcppExport SEXP _RMariaDB_connection_quote_string(SEXP conSEXP, SEXP xsSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbConnection* >::type con(conSEXP); - Rcpp::traits::input_parameter< CharacterVector >::type xs(xsSEXP); - rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + Rcpp::traits::input_parameter::type xs(xsSEXP); + rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); + return rcpp_result_gen; + END_RCPP } // connection_begin_transaction void connection_begin_transaction(XPtr con); RcppExport SEXP _RMariaDB_connection_begin_transaction(SEXP conSEXP) { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type con(conSEXP); - connection_begin_transaction(con); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_begin_transaction(con); + return R_NilValue; + END_RCPP } // connection_commit void connection_commit(XPtr con); RcppExport SEXP _RMariaDB_connection_commit(SEXP conSEXP) { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type con(conSEXP); - connection_commit(con); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_commit(con); + return R_NilValue; + END_RCPP } // connection_rollback void connection_rollback(XPtr con); RcppExport SEXP _RMariaDB_connection_rollback(SEXP conSEXP) { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type con(conSEXP); - connection_rollback(con); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_rollback(con); + return R_NilValue; + END_RCPP } // connection_is_transacting bool connection_is_transacting(DbConnection* con); RcppExport SEXP _RMariaDB_connection_is_transacting(SEXP conSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbConnection* >::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); + return rcpp_result_gen; + END_RCPP } // driver_init void driver_init(); RcppExport SEXP _RMariaDB_driver_init() { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_init(); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_init(); + return R_NilValue; + END_RCPP } // driver_done void driver_done(); RcppExport SEXP _RMariaDB_driver_done() { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_done(); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_done(); + return R_NilValue; + END_RCPP } // version IntegerVector version(); RcppExport SEXP _RMariaDB_version() { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - rcpp_result_gen = Rcpp::wrap(version()); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = Rcpp::wrap(version()); + return rcpp_result_gen; + END_RCPP } // init_logging void init_logging(const std::string& log_level); RcppExport SEXP _RMariaDB_init_logging(SEXP log_levelSEXP) { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string& >::type log_level(log_levelSEXP); - init_logging(log_level); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type log_level( + log_levelSEXP); + init_logging(log_level); + return R_NilValue; + END_RCPP } // result_create -XPtr result_create(XPtr con, std::string sql, bool is_statement); -RcppExport SEXP _RMariaDB_result_create(SEXP conSEXP, SEXP sqlSEXP, SEXP is_statementSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type con(conSEXP); - Rcpp::traits::input_parameter< std::string >::type sql(sqlSEXP); - Rcpp::traits::input_parameter< bool >::type is_statement(is_statementSEXP); - rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); - return rcpp_result_gen; -END_RCPP +XPtr result_create(XPtr con, std::string sql, + bool is_statement); +RcppExport SEXP _RMariaDB_result_create(SEXP conSEXP, SEXP sqlSEXP, + SEXP is_statementSEXP) { + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + Rcpp::traits::input_parameter::type sql(sqlSEXP); + Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); + rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); + return rcpp_result_gen; + END_RCPP } // result_release void result_release(XPtr res); RcppExport SEXP _RMariaDB_result_release(SEXP resSEXP) { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type res(resSEXP); - result_release(res); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res(resSEXP); + result_release(res); + return R_NilValue; + END_RCPP } // result_valid bool result_valid(XPtr res_); RcppExport SEXP _RMariaDB_result_valid(SEXP res_SEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< XPtr >::type res_(res_SEXP); - rcpp_result_gen = Rcpp::wrap(result_valid(res_)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res_(res_SEXP); + rcpp_result_gen = Rcpp::wrap(result_valid(res_)); + return rcpp_result_gen; + END_RCPP } // result_fetch List result_fetch(DbResult* res, const int n); RcppExport SEXP _RMariaDB_result_fetch(SEXP resSEXP, SEXP nSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbResult* >::type res(resSEXP); - Rcpp::traits::input_parameter< const int >::type n(nSEXP); - rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type n(nSEXP); + rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); + return rcpp_result_gen; + END_RCPP } // result_bind void result_bind(DbResult* res, List params); RcppExport SEXP _RMariaDB_result_bind(SEXP resSEXP, SEXP paramsSEXP) { -BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbResult* >::type res(resSEXP); - Rcpp::traits::input_parameter< List >::type params(paramsSEXP); - result_bind(res, params); - return R_NilValue; -END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type params(paramsSEXP); + result_bind(res, params); + return R_NilValue; + END_RCPP } // result_has_completed bool result_has_completed(DbResult* res); RcppExport SEXP _RMariaDB_result_has_completed(SEXP resSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbResult* >::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_fetched int result_rows_fetched(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_fetched(SEXP resSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbResult* >::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_affected int result_rows_affected(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_affected(SEXP resSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbResult* >::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); + return rcpp_result_gen; + END_RCPP } // result_column_info List result_column_info(DbResult* res); RcppExport SEXP _RMariaDB_result_column_info(SEXP resSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< DbResult* >::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_column_info(res)); - return rcpp_result_gen; -END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_column_info(res)); + return rcpp_result_gen; + END_RCPP } static const R_CallMethodDef CallEntries[] = { - {"_RMariaDB_connection_create", (DL_FUNC) &_RMariaDB_connection_create, 16}, - {"_RMariaDB_connection_valid", (DL_FUNC) &_RMariaDB_connection_valid, 1}, - {"_RMariaDB_connection_release", (DL_FUNC) &_RMariaDB_connection_release, 1}, - {"_RMariaDB_connection_info", (DL_FUNC) &_RMariaDB_connection_info, 1}, - {"_RMariaDB_connection_quote_string", (DL_FUNC) &_RMariaDB_connection_quote_string, 2}, - {"_RMariaDB_connection_begin_transaction", (DL_FUNC) &_RMariaDB_connection_begin_transaction, 1}, - {"_RMariaDB_connection_commit", (DL_FUNC) &_RMariaDB_connection_commit, 1}, - {"_RMariaDB_connection_rollback", (DL_FUNC) &_RMariaDB_connection_rollback, 1}, - {"_RMariaDB_connection_is_transacting", (DL_FUNC) &_RMariaDB_connection_is_transacting, 1}, - {"_RMariaDB_driver_init", (DL_FUNC) &_RMariaDB_driver_init, 0}, - {"_RMariaDB_driver_done", (DL_FUNC) &_RMariaDB_driver_done, 0}, - {"_RMariaDB_version", (DL_FUNC) &_RMariaDB_version, 0}, - {"_RMariaDB_init_logging", (DL_FUNC) &_RMariaDB_init_logging, 1}, - {"_RMariaDB_result_create", (DL_FUNC) &_RMariaDB_result_create, 3}, - {"_RMariaDB_result_release", (DL_FUNC) &_RMariaDB_result_release, 1}, - {"_RMariaDB_result_valid", (DL_FUNC) &_RMariaDB_result_valid, 1}, - {"_RMariaDB_result_fetch", (DL_FUNC) &_RMariaDB_result_fetch, 2}, - {"_RMariaDB_result_bind", (DL_FUNC) &_RMariaDB_result_bind, 2}, - {"_RMariaDB_result_has_completed", (DL_FUNC) &_RMariaDB_result_has_completed, 1}, - {"_RMariaDB_result_rows_fetched", (DL_FUNC) &_RMariaDB_result_rows_fetched, 1}, - {"_RMariaDB_result_rows_affected", (DL_FUNC) &_RMariaDB_result_rows_affected, 1}, - {"_RMariaDB_result_column_info", (DL_FUNC) &_RMariaDB_result_column_info, 1}, - {NULL, NULL, 0} -}; + {"_RMariaDB_connection_create", (DL_FUNC)&_RMariaDB_connection_create, 16}, + {"_RMariaDB_connection_valid", (DL_FUNC)&_RMariaDB_connection_valid, 1}, + {"_RMariaDB_connection_release", (DL_FUNC)&_RMariaDB_connection_release, 1}, + {"_RMariaDB_connection_info", (DL_FUNC)&_RMariaDB_connection_info, 1}, + {"_RMariaDB_connection_quote_string", + (DL_FUNC)&_RMariaDB_connection_quote_string, 2}, + {"_RMariaDB_connection_begin_transaction", + (DL_FUNC)&_RMariaDB_connection_begin_transaction, 1}, + {"_RMariaDB_connection_commit", (DL_FUNC)&_RMariaDB_connection_commit, 1}, + {"_RMariaDB_connection_rollback", (DL_FUNC)&_RMariaDB_connection_rollback, + 1}, + {"_RMariaDB_connection_is_transacting", + (DL_FUNC)&_RMariaDB_connection_is_transacting, 1}, + {"_RMariaDB_driver_init", (DL_FUNC)&_RMariaDB_driver_init, 0}, + {"_RMariaDB_driver_done", (DL_FUNC)&_RMariaDB_driver_done, 0}, + {"_RMariaDB_version", (DL_FUNC)&_RMariaDB_version, 0}, + {"_RMariaDB_init_logging", (DL_FUNC)&_RMariaDB_init_logging, 1}, + {"_RMariaDB_result_create", (DL_FUNC)&_RMariaDB_result_create, 3}, + {"_RMariaDB_result_release", (DL_FUNC)&_RMariaDB_result_release, 1}, + {"_RMariaDB_result_valid", (DL_FUNC)&_RMariaDB_result_valid, 1}, + {"_RMariaDB_result_fetch", (DL_FUNC)&_RMariaDB_result_fetch, 2}, + {"_RMariaDB_result_bind", (DL_FUNC)&_RMariaDB_result_bind, 2}, + {"_RMariaDB_result_has_completed", (DL_FUNC)&_RMariaDB_result_has_completed, + 1}, + {"_RMariaDB_result_rows_fetched", (DL_FUNC)&_RMariaDB_result_rows_fetched, + 1}, + {"_RMariaDB_result_rows_affected", (DL_FUNC)&_RMariaDB_result_rows_affected, + 1}, + {"_RMariaDB_result_column_info", (DL_FUNC)&_RMariaDB_result_column_info, 1}, + {NULL, NULL, 0}}; -RcppExport void R_init_RMariaDB(DllInfo *dll) { - R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); - R_useDynamicSymbols(dll, FALSE); +RcppExport void R_init_RMariaDB(DllInfo* dll) { + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); } diff --git a/src/connection.cpp b/src/connection.cpp index 3ecf4aa9..f22151b0 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1,33 +1,24 @@ -#include "pch.h" #include "RMariaDB_types.h" +#include "pch.h" // [[Rcpp::export]] XPtr connection_create( - const Nullable& host, - const Nullable& user, - const Nullable& password, - const Nullable& db, - unsigned int port, - const Nullable& unix_socket, - unsigned long client_flag, - const Nullable& groups, - const Nullable& default_file, - const Nullable& ssl_key, - const Nullable& ssl_cert, - const Nullable& ssl_ca, - const Nullable& ssl_capath, - const Nullable& ssl_cipher, - int timeout, - bool reconnect -) { + const Nullable& host, const Nullable& user, + const Nullable& password, const Nullable& db, + unsigned int port, const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, bool reconnect) { LOG_VERBOSE; DbConnection* pConnPtr = new DbConnection; try { - pConnPtr->connect( - host, user, password, db, port, unix_socket, client_flag, groups, default_file, - ssl_key, ssl_cert, ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect - ); + pConnPtr->connect(host, user, password, db, port, unix_socket, client_flag, + groups, default_file, ssl_key, ssl_cert, ssl_ca, + ssl_capath, ssl_cipher, timeout, reconnect); } catch (...) { delete pConnPtr; throw; @@ -57,9 +48,7 @@ void connection_release(XPtr con_) { } // [[Rcpp::export]] -List connection_info(DbConnection* con) { - return con->info(); -} +List connection_info(DbConnection* con) { return con->info(); } // Quoting @@ -84,34 +73,27 @@ void connection_begin_transaction(XPtr con) { } // [[Rcpp::export]] -void connection_commit(XPtr con) { - (*con)->commit(); -} +void connection_commit(XPtr con) { (*con)->commit(); } // [[Rcpp::export]] -void connection_rollback(XPtr con) { - (*con)->rollback(); -} +void connection_rollback(XPtr con) { (*con)->rollback(); } // [[Rcpp::export]] bool connection_is_transacting(DbConnection* con) { return con->is_transacting(); } - // Specific functions - // as() override namespace Rcpp { -template<> +template <> DbConnection* as(SEXP x) { DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); - if (!connection) - stop("Invalid connection"); + if (!connection) stop("Invalid connection"); return connection->get(); } -} +} // namespace Rcpp diff --git a/src/driver.cpp b/src/driver.cpp index 37db4c8f..73444aab 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -8,27 +8,18 @@ #define SERVER_VERSION "" #endif - // [[Rcpp::export]] -void driver_init() { - mysql_library_init(0, NULL, NULL); -} +void driver_init() { mysql_library_init(0, NULL, NULL); } // [[Rcpp::export]] -void driver_done() { - mysql_library_end(); -} +void driver_done() { mysql_library_end(); } // [[Rcpp::export]] IntegerVector version() { - return - IntegerVector::create( + return IntegerVector::create( _[SERVER_VERSION] = MYSQL_VERSION_ID, - _[mysql_get_client_info()] = mysql_get_client_version() - ); + _[mysql_get_client_info()] = mysql_get_client_version()); } // [[Rcpp::export]] -void init_logging(const std::string& log_level) { - plog::init_r(log_level); -} +void init_logging(const std::string& log_level) { plog::init_r(log_level); } diff --git a/src/integer64.h b/src/integer64.h index dfa12ea5..2f3b934c 100644 --- a/src/integer64.h +++ b/src/integer64.h @@ -9,4 +9,4 @@ inline int64_t* INTEGER64(SEXP x) { return reinterpret_cast(REAL(x)); } -#endif // RMARIADB_INTEGER64_H +#endif // RMARIADB_INTEGER64_H diff --git a/src/pch.h b/src/pch.h index f11d93e9..81e2cf21 100644 --- a/src/pch.h +++ b/src/pch.h @@ -1,6 +1,5 @@ #include #include - #include using namespace Rcpp; diff --git a/src/result.cpp b/src/result.cpp index 03e3da7b..30e7289a 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -1,19 +1,17 @@ -#include "pch.h" -#include "RMariaDB_types.h" #include "MariaResult.h" - +#include "RMariaDB_types.h" +#include "pch.h" // [[Rcpp::export]] -XPtr result_create(XPtr con, std::string sql, bool is_statement = false) { +XPtr result_create(XPtr con, std::string sql, + bool is_statement = false) { (*con)->check_connection(); DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); return XPtr(res, true); } // [[Rcpp::export]] -void result_release(XPtr res) { - res.release(); -} +void result_release(XPtr res) { res.release(); } // [[Rcpp::export]] bool result_valid(XPtr res_) { @@ -22,43 +20,30 @@ bool result_valid(XPtr res_) { } // [[Rcpp::export]] -List result_fetch(DbResult* res, const int n) { - return res->fetch(n); -} +List result_fetch(DbResult* res, const int n) { return res->fetch(n); } // [[Rcpp::export]] -void result_bind(DbResult* res, List params) { - res->bind(params); -} +void result_bind(DbResult* res, List params) { res->bind(params); } // [[Rcpp::export]] -bool result_has_completed(DbResult* res) { - return res->complete(); -} +bool result_has_completed(DbResult* res) { return res->complete(); } // [[Rcpp::export]] -int result_rows_fetched(DbResult* res) { - return res->n_rows_fetched(); -} +int result_rows_fetched(DbResult* res) { return res->n_rows_fetched(); } // [[Rcpp::export]] -int result_rows_affected(DbResult* res) { - return res->n_rows_affected(); -} +int result_rows_affected(DbResult* res) { return res->n_rows_affected(); } // [[Rcpp::export]] -List result_column_info(DbResult* res) { - return res->get_column_info(); -} +List result_column_info(DbResult* res) { return res->get_column_info(); } namespace Rcpp { -template<> +template <> DbResult* as(SEXP x) { DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); - if (!result) - stop("Invalid result set"); + if (!result) stop("Invalid result set"); return result; } -} +} // namespace Rcpp From a9b9d3370292f048263252cbe3fa7830ff9d4b41 Mon Sep 17 00:00:00 2001 From: Antonov Misha Date: Tue, 15 Nov 2022 11:26:14 +0000 Subject: [PATCH 3/9] remove single line functions --- .clang-format | 4 ++-- src/DbConnection.cpp | 16 ++++++++++++---- src/DbResult.cpp | 16 ++++++++++++---- src/MariaBinding.cpp | 6 ++++-- src/MariaResultImpl.cpp | 6 ++++-- src/MariaResultPrep.cpp | 8 ++++++-- src/MariaResultSimple.cpp | 24 ++++++++++++++++++------ src/MariaRow.cpp | 10 +++++++--- src/connection.cpp | 12 +++++++++--- src/driver.cpp | 12 +++++++++--- src/result.cpp | 28 +++++++++++++++++++++------- 11 files changed, 104 insertions(+), 38 deletions(-) diff --git a/.clang-format b/.clang-format index f01f27cd..704dfb96 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,3 @@ -Language: Cpp - BasedOnStyle: Google +Language: Cpp +AllowShortFunctionsOnASingleLine: None \ No newline at end of file diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index b472b0d4..26be16eb 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -93,7 +93,9 @@ void DbConnection::disconnect() { pConn_ = NULL; } -bool DbConnection::is_valid() { return !!get_conn(); } +bool DbConnection::is_valid() { + return !!get_conn(); +} void DbConnection::check_connection() { if (!is_valid()) { @@ -113,7 +115,9 @@ List DbConnection::info() { _["thread.id"] = (int)mysql_thread_id(pConn_)); } -MYSQL* DbConnection::get_conn() { return pConn_; } +MYSQL* DbConnection::get_conn() { + return pConn_; +} SEXP DbConnection::quote_string(const String& input) { if (input == NA_STRING) return get_null_string(); @@ -161,7 +165,9 @@ bool DbConnection::is_current_result(const DbResult* pResult) const { return pCurrentResult_ == pResult; } -bool DbConnection::has_query() { return pCurrentResult_ != NULL; } +bool DbConnection::has_query() { + return pCurrentResult_ != NULL; +} bool DbConnection::exec(const std::string& sql) { check_connection(); @@ -200,7 +206,9 @@ void DbConnection::rollback() { transacting_ = false; } -bool DbConnection::is_transacting() const { return transacting_; } +bool DbConnection::is_transacting() const { + return transacting_; +} void DbConnection::autocommit() { if (!is_transacting() && get_conn()) { diff --git a/src/DbResult.cpp b/src/DbResult.cpp index 0f751124..2ad6dc25 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -25,13 +25,21 @@ DbResult::~DbResult() { // Publics ///////////////////////////////////////////////////////////////////// -bool DbResult::complete() const { return (impl == NULL) || impl->complete(); } +bool DbResult::complete() const { + return (impl == NULL) || impl->complete(); +} -bool DbResult::is_active() const { return pConn_->is_current_result(this); } +bool DbResult::is_active() const { + return pConn_->is_current_result(this); +} -int DbResult::n_rows_fetched() { return impl->n_rows_fetched(); } +int DbResult::n_rows_fetched() { + return impl->n_rows_fetched(); +} -int DbResult::n_rows_affected() { return impl->n_rows_affected(); } +int DbResult::n_rows_affected() { + return impl->n_rows_affected(); +} void DbResult::bind(const List& params) { validate_params(params); diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index b360f100..d9537bb1 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -5,9 +5,11 @@ #include "integer64.h" #include "pch.h" -MariaBinding::MariaBinding() : statement(NULL), p(0), i(0), n_rows(0) {} +MariaBinding::MariaBinding() : statement(NULL), p(0), i(0), n_rows(0) { +} -MariaBinding::~MariaBinding() {} +MariaBinding::~MariaBinding() { +} void MariaBinding::setup(MYSQL_STMT* statement_) { LOG_VERBOSE; diff --git a/src/MariaResultImpl.cpp b/src/MariaResultImpl.cpp index 739e4eb5..8082f1a0 100644 --- a/src/MariaResultImpl.cpp +++ b/src/MariaResultImpl.cpp @@ -2,6 +2,8 @@ #include "pch.h" -MariaResultImpl::MariaResultImpl() {} +MariaResultImpl::MariaResultImpl() { +} -MariaResultImpl::~MariaResultImpl() {} +MariaResultImpl::~MariaResultImpl() { +} diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index 93466c86..60168537 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -22,7 +22,9 @@ MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, if (pStatement_ == NULL) stop("Out of memory"); } -MariaResultPrep::~MariaResultPrep() { MariaResultPrep::close(); } +MariaResultPrep::~MariaResultPrep() { + MariaResultPrep::close(); +} void MariaResultPrep::send_query(const std::string& sql) { LOG_DEBUG << sql; @@ -118,7 +120,9 @@ List MariaResultPrep::get_column_info() { return List::create(_["name"] = names, _["type"] = types); } -bool MariaResultPrep::has_result() const { return pSpec_ != NULL; } +bool MariaResultPrep::has_result() const { + return pSpec_ != NULL; +} bool MariaResultPrep::step() { LOG_VERBOSE; diff --git a/src/MariaResultSimple.cpp b/src/MariaResultSimple.cpp index a5539f5f..cb27c135 100644 --- a/src/MariaResultSimple.cpp +++ b/src/MariaResultSimple.cpp @@ -9,7 +9,9 @@ MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, (void)is_statement; } -MariaResultSimple::~MariaResultSimple() { MariaResultSimple::close(); } +MariaResultSimple::~MariaResultSimple() { + MariaResultSimple::close(); +} void MariaResultSimple::send_query(const std::string& sql) { LOG_DEBUG << sql; @@ -17,7 +19,9 @@ void MariaResultSimple::send_query(const std::string& sql) { exec(sql); } -void MariaResultSimple::close() { LOG_VERBOSE; } +void MariaResultSimple::close() { + LOG_VERBOSE; +} void MariaResultSimple::bind(const List& /*params*/) { LOG_VERBOSE; @@ -43,10 +47,18 @@ List MariaResultSimple::fetch(int /*n_max*/) { 0); } -int MariaResultSimple::n_rows_affected() { return 0; } +int MariaResultSimple::n_rows_affected() { + return 0; +} -int MariaResultSimple::n_rows_fetched() { return 0; } +int MariaResultSimple::n_rows_fetched() { + return 0; +} -bool MariaResultSimple::complete() const { return true; } +bool MariaResultSimple::complete() const { + return true; +} -void MariaResultSimple::exec(const std::string& sql) { pConn_->exec(sql); } +void MariaResultSimple::exec(const std::string& sql) { + pConn_->exec(sql); +} diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index 925ec11d..dc702763 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -5,9 +5,11 @@ #include "integer64.h" #include "pch.h" -MariaRow::MariaRow() : pStatement_(NULL), n_(0) {} +MariaRow::MariaRow() : pStatement_(NULL), n_(0) { +} -MariaRow::~MariaRow() {} +MariaRow::~MariaRow() { +} void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& types) { @@ -105,7 +107,9 @@ void MariaRow::setup(MYSQL_STMT* pStatement, } } -bool MariaRow::is_null(int j) { return nulls_[j] == 1; } +bool MariaRow::is_null(int j) { + return nulls_[j] == 1; +} int MariaRow::value_bool(int j) { if (is_null(j)) { diff --git a/src/connection.cpp b/src/connection.cpp index f22151b0..054d1a16 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -48,7 +48,9 @@ void connection_release(XPtr con_) { } // [[Rcpp::export]] -List connection_info(DbConnection* con) { return con->info(); } +List connection_info(DbConnection* con) { + return con->info(); +} // Quoting @@ -73,10 +75,14 @@ void connection_begin_transaction(XPtr con) { } // [[Rcpp::export]] -void connection_commit(XPtr con) { (*con)->commit(); } +void connection_commit(XPtr con) { + (*con)->commit(); +} // [[Rcpp::export]] -void connection_rollback(XPtr con) { (*con)->rollback(); } +void connection_rollback(XPtr con) { + (*con)->rollback(); +} // [[Rcpp::export]] bool connection_is_transacting(DbConnection* con) { diff --git a/src/driver.cpp b/src/driver.cpp index 73444aab..aa940f86 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -9,10 +9,14 @@ #endif // [[Rcpp::export]] -void driver_init() { mysql_library_init(0, NULL, NULL); } +void driver_init() { + mysql_library_init(0, NULL, NULL); +} // [[Rcpp::export]] -void driver_done() { mysql_library_end(); } +void driver_done() { + mysql_library_end(); +} // [[Rcpp::export]] IntegerVector version() { @@ -22,4 +26,6 @@ IntegerVector version() { } // [[Rcpp::export]] -void init_logging(const std::string& log_level) { plog::init_r(log_level); } +void init_logging(const std::string& log_level) { + plog::init_r(log_level); +} diff --git a/src/result.cpp b/src/result.cpp index 30e7289a..19937a2f 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -11,7 +11,9 @@ XPtr result_create(XPtr con, std::string sql, } // [[Rcpp::export]] -void result_release(XPtr res) { res.release(); } +void result_release(XPtr res) { + res.release(); +} // [[Rcpp::export]] bool result_valid(XPtr res_) { @@ -20,22 +22,34 @@ bool result_valid(XPtr res_) { } // [[Rcpp::export]] -List result_fetch(DbResult* res, const int n) { return res->fetch(n); } +List result_fetch(DbResult* res, const int n) { + return res->fetch(n); +} // [[Rcpp::export]] -void result_bind(DbResult* res, List params) { res->bind(params); } +void result_bind(DbResult* res, List params) { + res->bind(params); +} // [[Rcpp::export]] -bool result_has_completed(DbResult* res) { return res->complete(); } +bool result_has_completed(DbResult* res) { + return res->complete(); +} // [[Rcpp::export]] -int result_rows_fetched(DbResult* res) { return res->n_rows_fetched(); } +int result_rows_fetched(DbResult* res) { + return res->n_rows_fetched(); +} // [[Rcpp::export]] -int result_rows_affected(DbResult* res) { return res->n_rows_affected(); } +int result_rows_affected(DbResult* res) { + return res->n_rows_affected(); +} // [[Rcpp::export]] -List result_column_info(DbResult* res) { return res->get_column_info(); } +List result_column_info(DbResult* res) { + return res->get_column_info(); +} namespace Rcpp { From 4120d8a6d66e85d06746837abb2da042b924da10 Mon Sep 17 00:00:00 2001 From: Antonov Misha Date: Tue, 15 Nov 2022 11:31:50 +0000 Subject: [PATCH 4/9] remove single line if --- .clang-format | 3 ++- src/DbConnection.cpp | 27 ++++++++++++++++++--------- src/DbResult.cpp | 6 ++++-- src/MariaBinding.cpp | 3 ++- src/MariaResultPrep.cpp | 33 ++++++++++++++++++++++----------- src/MariaRow.cpp | 21 ++++++++++++++------- src/MariaTypes.cpp | 21 ++++++++++++++------- src/connection.cpp | 3 ++- src/result.cpp | 3 ++- 9 files changed, 80 insertions(+), 40 deletions(-) diff --git a/.clang-format b/.clang-format index 704dfb96..711e6c5b 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,4 @@ BasedOnStyle: Google Language: Cpp -AllowShortFunctionsOnASingleLine: None \ No newline at end of file +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never \ No newline at end of file diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index 26be16eb..b228c2c5 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -78,7 +78,8 @@ void DbConnection::connect( } void DbConnection::disconnect() { - if (!is_valid()) return; + if (!is_valid()) + return; if (has_query()) { warning("%s\n%s", "There is a result object still in use.", @@ -120,7 +121,8 @@ MYSQL* DbConnection::get_conn() { } SEXP DbConnection::quote_string(const String& input) { - if (input == NA_STRING) return get_null_string(); + if (input == NA_STRING) + return get_null_string(); const char* input_cstr = input.get_cstring(); size_t input_len = strlen(input_cstr); @@ -143,10 +145,12 @@ SEXP DbConnection::get_null_string() { } void DbConnection::set_current_result(DbResult* pResult) { - if (pResult == pCurrentResult_) return; + if (pResult == pCurrentResult_) + return; if (pCurrentResult_ != NULL) { - if (pResult != NULL) warning("Cancelling previous query"); + if (pResult != NULL) + warning("Cancelling previous query"); pCurrentResult_->close(); } @@ -155,7 +159,8 @@ void DbConnection::set_current_result(DbResult* pResult) { void DbConnection::reset_current_result(DbResult* pResult) { // FIXME: What to do if not current result is reset? - if (pResult != pCurrentResult_) return; + if (pResult != pCurrentResult_) + return; pCurrentResult_->close(); pCurrentResult_ = NULL; @@ -176,7 +181,8 @@ bool DbConnection::exec(const std::string& sql) { stop("Error executing query: %s", mysql_error(pConn_)); MYSQL_RES* res = mysql_store_result(pConn_); - if (res != NULL) mysql_free_result(res); + if (res != NULL) + mysql_free_result(res); autocommit(); @@ -184,14 +190,16 @@ bool DbConnection::exec(const std::string& sql) { } void DbConnection::begin_transaction() { - if (is_transacting()) stop("Nested transactions not supported."); + if (is_transacting()) + stop("Nested transactions not supported."); check_connection(); transacting_ = true; } void DbConnection::commit() { - if (!is_transacting()) stop("Call dbBegin() to start a transaction."); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); check_connection(); mysql_commit(get_conn()); @@ -199,7 +207,8 @@ void DbConnection::commit() { } void DbConnection::rollback() { - if (!is_transacting()) stop("Call dbBegin() to start a transaction."); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); check_connection(); mysql_rollback(get_conn()); diff --git a/src/DbResult.cpp b/src/DbResult.cpp index 2ad6dc25..a6e5a23c 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -47,7 +47,8 @@ void DbResult::bind(const List& params) { } List DbResult::fetch(const int n_max) { - if (!is_active()) stop("Inactive result set"); + if (!is_active()) + stop("Inactive result set"); return impl->fetch(n_max); } @@ -63,7 +64,8 @@ List DbResult::get_column_info() { void DbResult::close() { // Called from destructor - if (impl) impl->close(); + if (impl) + impl->close(); } // Privates /////////////////////////////////////////////////////////////////// diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index d9537bb1..af5c384f 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -84,7 +84,8 @@ void MariaBinding::init_binding(const List& params_) { bool MariaBinding::bind_next_row() { LOG_VERBOSE; - if (i >= n_rows) return false; + if (i >= n_rows) + return false; for (int j = 0; j < p; ++j) { LOG_VERBOSE << j << " -> " << type_name(types[j]); diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index 60168537..dafc4d28 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -19,7 +19,8 @@ MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, complete_(false), is_statement_(is_statement) { pStatement_ = mysql_stmt_init(pConn_->get_conn()); - if (pStatement_ == NULL) stop("Out of memory"); + if (pStatement_ == NULL) + stop("Out of memory"); } MariaResultPrep::~MariaResultPrep() { @@ -130,7 +131,8 @@ bool MariaResultPrep::step() { while (!fetch_row()) { LOG_VERBOSE; - if (!bindingInput_.bind_next_row()) return false; + if (!bindingInput_.bind_next_row()) + return false; execute(); } @@ -143,7 +145,8 @@ bool MariaResultPrep::step() { bool MariaResultPrep::fetch_row() { LOG_VERBOSE; - if (complete_) return false; + if (complete_) + return false; LOG_VERBOSE << "mysql_stmt_fetch()"; int result = mysql_stmt_fetch(pStatement_); @@ -165,7 +168,8 @@ bool MariaResultPrep::fetch_row() { } List MariaResultPrep::fetch(int n_max) { - if (!bound_) stop("Query needs to be bound before fetching"); + if (!bound_) + stop("Query needs to be bound before fetching"); if (!has_result()) { if (names_.size() == 0) { warning( @@ -177,14 +181,17 @@ List MariaResultPrep::fetch(int n_max) { int n = (n_max < 0) ? 100 : n_max; List out = df_create(types_, names_, n); - if (n == 0) return out; + if (n == 0) + return out; int i = 0; for (;;) { - if (i >= n && n_max > 0) break; + if (i >= n && n_max > 0) + break; - if (!step()) break; + if (!step()) + break; if (i >= n) { n *= 2; @@ -197,7 +204,8 @@ List MariaResultPrep::fetch(int n_max) { } ++i; - if (i % 1024 == 0) checkUserInterrupt(); + if (i % 1024 == 0) + checkUserInterrupt(); } // Trim back to what we actually used @@ -211,19 +219,22 @@ List MariaResultPrep::fetch(int n_max) { } int MariaResultPrep::n_rows_affected() { - if (!bound_) return NA_INTEGER; + if (!bound_) + return NA_INTEGER; // FIXME: > 2^32 rows? return static_cast(rowsAffected_); } int MariaResultPrep::n_rows_fetched() { - if (!bound_) return 0; + if (!bound_) + return 0; // FIXME: > 2^32 rows? return static_cast(rowsFetched_); } bool MariaResultPrep::complete() const { - if (!bound_) return FALSE; + if (!bound_) + return FALSE; return !has_result() || // query doesn't have results complete_; // we've fetched all available results } diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index dc702763..06ca8074 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -132,18 +132,21 @@ double MariaRow::value_double(int j) { } SEXP MariaRow::value_string(int j) { - if (is_null(j)) return NA_STRING; + if (is_null(j)) + return NA_STRING; fetch_buffer(j); int len = static_cast(buffers_[j].size()); - if (len == 0) return R_BlankString; + if (len == 0) + return R_BlankString; const char* val = reinterpret_cast(&buffers_[j][0]); return Rf_mkCharLenCE(val, len, CE_UTF8); } SEXP MariaRow::value_raw(int j) { - if (is_null(j)) return R_NilValue; + if (is_null(j)) + return R_NilValue; fetch_buffer(j); SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); @@ -153,7 +156,8 @@ SEXP MariaRow::value_raw(int j) { } double MariaRow::value_date_time(int j) { - if (is_null(j)) return NA_REAL; + if (is_null(j)) + return NA_REAL; MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; @@ -168,7 +172,8 @@ double MariaRow::value_date_time(int j) { } double MariaRow::value_date(int j) { - if (is_null(j)) return NA_REAL; + if (is_null(j)) + return NA_REAL; MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; @@ -179,7 +184,8 @@ double MariaRow::value_date(int j) { } double MariaRow::value_time(int j) { - if (is_null(j)) return NA_REAL; + if (is_null(j)) + return NA_REAL; MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; return static_cast(mytime->hour) * 3600.0 + @@ -225,7 +231,8 @@ void MariaRow::fetch_buffer(int j) { LOG_VERBOSE << length; buffers_[j].resize(length); - if (length == 0) return; + if (length == 0) + return; bindings_[j].buffer = &buffers_[j][0]; // might have moved bindings_[j].buffer_length = length; diff --git a/src/MariaTypes.cpp b/src/MariaTypes.cpp index be60c8f0..f381840f 100644 --- a/src/MariaTypes.cpp +++ b/src/MariaTypes.cpp @@ -108,7 +108,8 @@ SEXPTYPE type_sexp(MariaFieldType type) { std::string r_class(RObject x) { RObject klass_(x.attr("class")); std::string klass; - if (klass_ == R_NilValue) return ""; + if (klass_ == R_NilValue) + return ""; CharacterVector klassv = as(klass_); return std::string(klassv[klassv.length() - 1]); @@ -123,16 +124,22 @@ MariaFieldType variable_type_from_object(const RObject& type) { case INTSXP: return MY_INT32; case REALSXP: - if (klass == "Date") return MY_DATE; - if (klass == "POSIXt") return MY_DATE_TIME; - if (klass == "difftime") return MY_TIME; - if (klass == "integer64") return MY_INT64; + if (klass == "Date") + return MY_DATE; + if (klass == "POSIXt") + return MY_DATE_TIME; + if (klass == "difftime") + return MY_TIME; + if (klass == "integer64") + return MY_INT64; return MY_DBL; case STRSXP: return MY_STR; case VECSXP: - if (klass == "blob") return MY_RAW; - if (all_raw(type)) return MY_RAW; + if (klass == "blob") + return MY_RAW; + if (all_raw(type)) + return MY_RAW; break; } diff --git a/src/connection.cpp b/src/connection.cpp index 054d1a16..14e4fcbf 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -98,7 +98,8 @@ namespace Rcpp { template <> DbConnection* as(SEXP x) { DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); - if (!connection) stop("Invalid connection"); + if (!connection) + stop("Invalid connection"); return connection->get(); } diff --git a/src/result.cpp b/src/result.cpp index 19937a2f..6a11326b 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -56,7 +56,8 @@ namespace Rcpp { template <> DbResult* as(SEXP x) { DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); - if (!result) stop("Invalid result set"); + if (!result) + stop("Invalid result set"); return result; } From eb44c96ffa7ca1f5ed8ecb4352c48f4b3ee1c3da Mon Sep 17 00:00:00 2001 From: Antonov Misha Date: Tue, 15 Nov 2022 11:47:40 +0000 Subject: [PATCH 5/9] remove indent for access modifiers --- .clang-format | 6 +- src/DbConnection.cpp | 269 +++++++++++------------ src/DbConnection.h | 90 ++++---- src/DbResult.cpp | 73 ++++--- src/DbResult.h | 36 +-- src/MariaBinding.cpp | 450 +++++++++++++++++++------------------- src/MariaBinding.h | 42 ++-- src/MariaResult.cpp | 25 ++- src/MariaResult.h | 18 +- src/MariaResultImpl.h | 24 +- src/MariaResultPrep.cpp | 370 +++++++++++++++---------------- src/MariaResultPrep.h | 66 +++--- src/MariaResultSimple.cpp | 45 ++-- src/MariaResultSimple.h | 30 +-- src/MariaRow.cpp | 386 ++++++++++++++++---------------- src/MariaRow.h | 68 +++--- src/MariaTypes.cpp | 264 +++++++++++----------- src/MariaTypes.h | 18 +- src/RcppExports.cpp | 361 +++++++++++++++--------------- src/connection.cpp | 76 +++---- src/driver.cpp | 12 +- src/integer64.h | 2 +- src/result.cpp | 32 +-- 23 files changed, 1388 insertions(+), 1375 deletions(-) diff --git a/.clang-format b/.clang-format index 711e6c5b..d2139802 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,8 @@ BasedOnStyle: Google Language: Cpp +TabWidth: 4 +IndentWidth: 4 +UseTab: ForIndentation AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Never \ No newline at end of file +AllowShortIfStatementsOnASingleLine: Never +AccessModifierOffset: -4 \ No newline at end of file diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index b228c2c5..d02ffe58 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -5,16 +5,16 @@ DbConnection::DbConnection() : pConn_(NULL), pCurrentResult_(NULL), transacting_(false) { - LOG_VERBOSE; + LOG_VERBOSE; } DbConnection::~DbConnection() { - LOG_VERBOSE; + LOG_VERBOSE; - if (is_valid()) { - warning("call dbDisconnect() when finished working with a connection"); - disconnect(); - } + if (is_valid()) { + warning("call dbDisconnect() when finished working with a connection"); + disconnect(); + } } void DbConnection::connect( @@ -27,200 +27,201 @@ void DbConnection::connect( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; - - this->pConn_ = mysql_init(NULL); - // Enable LOCAL INFILE for fast data ingest - unsigned int local_infile = 1; - mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); - // Default to UTF-8 - mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); - if (!groups.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, - as(groups).c_str()); - if (!default_file.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, - as(default_file).c_str()); - - if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || - !ssl_capath.isNull() || !ssl_cipher.isNull()) { - mysql_ssl_set( - this->pConn_, - ssl_key.isNull() ? NULL : as(ssl_key).c_str(), - ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), - ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), - ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), - ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); - } - if (timeout > 0) { - mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); - } - if (reconnect) { - my_bool reconnect_ = 1; - mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); - } - - LOG_VERBOSE; - - if (!mysql_real_connect( - this->pConn_, host.isNull() ? NULL : as(host).c_str(), - user.isNull() ? NULL : as(user).c_str(), - password.isNull() ? NULL : as(password).c_str(), - db.isNull() ? NULL : as(db).c_str(), port, - unix_socket.isNull() ? NULL : as(unix_socket).c_str(), - client_flag)) { - std::string error = mysql_error(this->pConn_); - mysql_close(this->pConn_); - this->pConn_ = NULL; - - stop("Failed to connect: %s", error.c_str()); - } + LOG_VERBOSE; + + this->pConn_ = mysql_init(NULL); + // Enable LOCAL INFILE for fast data ingest + unsigned int local_infile = 1; + mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); + // Default to UTF-8 + mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); + if (!groups.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, + as(groups).c_str()); + if (!default_file.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, + as(default_file).c_str()); + + if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || + !ssl_capath.isNull() || !ssl_cipher.isNull()) { + mysql_ssl_set( + this->pConn_, + ssl_key.isNull() ? NULL : as(ssl_key).c_str(), + ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), + ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), + ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), + ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); + } + if (timeout > 0) { + mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); + } + if (reconnect) { + my_bool reconnect_ = 1; + mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); + } + + LOG_VERBOSE; + + if (!mysql_real_connect( + this->pConn_, host.isNull() ? NULL : as(host).c_str(), + user.isNull() ? NULL : as(user).c_str(), + password.isNull() ? NULL : as(password).c_str(), + db.isNull() ? NULL : as(db).c_str(), port, + unix_socket.isNull() ? NULL : as(unix_socket).c_str(), + client_flag)) { + std::string error = mysql_error(this->pConn_); + mysql_close(this->pConn_); + this->pConn_ = NULL; + + stop("Failed to connect: %s", error.c_str()); + } } void DbConnection::disconnect() { - if (!is_valid()) - return; + if (!is_valid()) + return; - if (has_query()) { - warning("%s\n%s", "There is a result object still in use.", - "The connection will be automatically released when it is closed"); - } + if (has_query()) { + warning( + "%s\n%s", "There is a result object still in use.", + "The connection will be automatically released when it is closed"); + } - try { - mysql_close(get_conn()); - } catch (...) { - }; + try { + mysql_close(get_conn()); + } catch (...) { + }; - pConn_ = NULL; + pConn_ = NULL; } bool DbConnection::is_valid() { - return !!get_conn(); + return !!get_conn(); } void DbConnection::check_connection() { - if (!is_valid()) { - stop("Invalid or closed connection"); - } + if (!is_valid()) { + stop("Invalid or closed connection"); + } } List DbConnection::info() { - return List::create( - _["host"] = std::string(pConn_->host), - _["username"] = std::string(pConn_->user), - _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), - _["con.type"] = std::string(mysql_get_host_info(pConn_)), - _["db.version"] = std::string(mysql_get_server_info(pConn_)), - _["port"] = NA_INTEGER, - _["protocol.version"] = (int)mysql_get_proto_info(pConn_), - _["thread.id"] = (int)mysql_thread_id(pConn_)); + return List::create( + _["host"] = std::string(pConn_->host), + _["username"] = std::string(pConn_->user), + _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), + _["con.type"] = std::string(mysql_get_host_info(pConn_)), + _["db.version"] = std::string(mysql_get_server_info(pConn_)), + _["port"] = NA_INTEGER, + _["protocol.version"] = (int)mysql_get_proto_info(pConn_), + _["thread.id"] = (int)mysql_thread_id(pConn_)); } MYSQL* DbConnection::get_conn() { - return pConn_; + return pConn_; } SEXP DbConnection::quote_string(const String& input) { - if (input == NA_STRING) - return get_null_string(); + if (input == NA_STRING) + return get_null_string(); - const char* input_cstr = input.get_cstring(); - size_t input_len = strlen(input_cstr); + const char* input_cstr = input.get_cstring(); + size_t input_len = strlen(input_cstr); - // Create buffer with enough room to escape every character - std::string output = "'"; - output.resize(input_len * 2 + 3); + // Create buffer with enough room to escape every character + std::string output = "'"; + output.resize(input_len * 2 + 3); - size_t end = - mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); + size_t end = + mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); - output.resize(end + 1); - output.append("'"); - return Rf_mkCharCE(output.c_str(), CE_UTF8); + output.resize(end + 1); + output.append("'"); + return Rf_mkCharCE(output.c_str(), CE_UTF8); } SEXP DbConnection::get_null_string() { - static RObject null = Rf_mkCharCE("NULL", CE_UTF8); - return null; + static RObject null = Rf_mkCharCE("NULL", CE_UTF8); + return null; } void DbConnection::set_current_result(DbResult* pResult) { - if (pResult == pCurrentResult_) - return; + if (pResult == pCurrentResult_) + return; - if (pCurrentResult_ != NULL) { - if (pResult != NULL) - warning("Cancelling previous query"); + if (pCurrentResult_ != NULL) { + if (pResult != NULL) + warning("Cancelling previous query"); - pCurrentResult_->close(); - } - pCurrentResult_ = pResult; + pCurrentResult_->close(); + } + pCurrentResult_ = pResult; } void DbConnection::reset_current_result(DbResult* pResult) { - // FIXME: What to do if not current result is reset? - if (pResult != pCurrentResult_) - return; + // FIXME: What to do if not current result is reset? + if (pResult != pCurrentResult_) + return; - pCurrentResult_->close(); - pCurrentResult_ = NULL; + pCurrentResult_->close(); + pCurrentResult_ = NULL; } bool DbConnection::is_current_result(const DbResult* pResult) const { - return pCurrentResult_ == pResult; + return pCurrentResult_ == pResult; } bool DbConnection::has_query() { - return pCurrentResult_ != NULL; + return pCurrentResult_ != NULL; } bool DbConnection::exec(const std::string& sql) { - check_connection(); + check_connection(); - if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) - stop("Error executing query: %s", mysql_error(pConn_)); + if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) + stop("Error executing query: %s", mysql_error(pConn_)); - MYSQL_RES* res = mysql_store_result(pConn_); - if (res != NULL) - mysql_free_result(res); + MYSQL_RES* res = mysql_store_result(pConn_); + if (res != NULL) + mysql_free_result(res); - autocommit(); + autocommit(); - return true; + return true; } void DbConnection::begin_transaction() { - if (is_transacting()) - stop("Nested transactions not supported."); - check_connection(); + if (is_transacting()) + stop("Nested transactions not supported."); + check_connection(); - transacting_ = true; + transacting_ = true; } void DbConnection::commit() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_commit(get_conn()); - transacting_ = false; + mysql_commit(get_conn()); + transacting_ = false; } void DbConnection::rollback() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_rollback(get_conn()); - transacting_ = false; + mysql_rollback(get_conn()); + transacting_ = false; } bool DbConnection::is_transacting() const { - return transacting_; + return transacting_; } void DbConnection::autocommit() { - if (!is_transacting() && get_conn()) { - mysql_commit(get_conn()); - } + if (!is_transacting() && get_conn()) { + mysql_commit(get_conn()); + } } diff --git a/src/DbConnection.h b/src/DbConnection.h index 2531fd3b..e9179e94 100644 --- a/src/DbConnection.h +++ b/src/DbConnection.h @@ -11,51 +11,51 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class DbConnection : boost::noncopyable { - MYSQL* pConn_; - DbResult* pCurrentResult_; - bool transacting_; - - public: - DbConnection(); - ~DbConnection(); - - public: - void connect(const Nullable& host, - const Nullable& user, - const Nullable& password, - const Nullable& db, unsigned int port, - const Nullable& unix_socket, - unsigned long client_flag, const Nullable& groups, - const Nullable& default_file, - const Nullable& ssl_key, - const Nullable& ssl_cert, - const Nullable& ssl_ca, - const Nullable& ssl_capath, - const Nullable& ssl_cipher, int timeout, - bool reconnect); - void disconnect(); - bool is_valid(); - void check_connection(); - - List info(); - MYSQL* get_conn(); - - SEXP quote_string(const String& input); - static SEXP get_null_string(); - - // Cancels previous query, if needed. - void set_current_result(DbResult* pResult); - void reset_current_result(DbResult* pResult); - bool is_current_result(const DbResult* pResult) const; - bool has_query(); - - bool exec(const std::string& sql); - - void begin_transaction(); - void commit(); - void rollback(); - bool is_transacting() const; - void autocommit(); + MYSQL* pConn_; + DbResult* pCurrentResult_; + bool transacting_; + +public: + DbConnection(); + ~DbConnection(); + +public: + void connect(const Nullable& host, + const Nullable& user, + const Nullable& password, + const Nullable& db, unsigned int port, + const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, + const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, + bool reconnect); + void disconnect(); + bool is_valid(); + void check_connection(); + + List info(); + MYSQL* get_conn(); + + SEXP quote_string(const String& input); + static SEXP get_null_string(); + + // Cancels previous query, if needed. + void set_current_result(DbResult* pResult); + void reset_current_result(DbResult* pResult); + bool is_current_result(const DbResult* pResult) const; + bool has_query(); + + bool exec(const std::string& sql); + + void begin_transaction(); + void commit(); + void rollback(); + bool is_transacting() const; + void autocommit(); }; #endif diff --git a/src/DbResult.cpp b/src/DbResult.cpp index a6e5a23c..440c111a 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -7,78 +7,79 @@ // Construction //////////////////////////////////////////////////////////////// DbResult::DbResult(const DbConnectionPtr& pConn) : pConn_(pConn) { - pConn_->check_connection(); + pConn_->check_connection(); - // subclass constructor can throw, the destructor will remove the - // current result set - pConn_->set_current_result(this); + // subclass constructor can throw, the destructor will remove the + // current result set + pConn_->set_current_result(this); } DbResult::~DbResult() { - try { - if (is_active()) { - pConn_->reset_current_result(this); - } - } catch (...) { - } + try { + if (is_active()) { + pConn_->reset_current_result(this); + } + } catch (...) { + } } // Publics ///////////////////////////////////////////////////////////////////// bool DbResult::complete() const { - return (impl == NULL) || impl->complete(); + return (impl == NULL) || impl->complete(); } bool DbResult::is_active() const { - return pConn_->is_current_result(this); + return pConn_->is_current_result(this); } int DbResult::n_rows_fetched() { - return impl->n_rows_fetched(); + return impl->n_rows_fetched(); } int DbResult::n_rows_affected() { - return impl->n_rows_affected(); + return impl->n_rows_affected(); } void DbResult::bind(const List& params) { - validate_params(params); - impl->bind(params); + validate_params(params); + impl->bind(params); } List DbResult::fetch(const int n_max) { - if (!is_active()) - stop("Inactive result set"); + if (!is_active()) + stop("Inactive result set"); - return impl->fetch(n_max); + return impl->fetch(n_max); } List DbResult::get_column_info() { - List out = impl->get_column_info(); + List out = impl->get_column_info(); - out.attr("row.names") = IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); - out.attr("class") = "data.frame"; + out.attr("row.names") = + IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); + out.attr("class") = "data.frame"; - return out; + return out; } void DbResult::close() { - // Called from destructor - if (impl) - impl->close(); + // Called from destructor + if (impl) + impl->close(); } // Privates /////////////////////////////////////////////////////////////////// void DbResult::validate_params(const List& params) const { - if (params.size() != 0) { - SEXP first_col = params[0]; - int n = Rf_length(first_col); - - for (int j = 1; j < params.size(); ++j) { - SEXP col = params[j]; - if (Rf_length(col) != n) - stop("Parameter %i does not have length %d.", j + 1, n); - } - } + if (params.size() != 0) { + SEXP first_col = params[0]; + int n = Rf_length(first_col); + + for (int j = 1; j < params.size(); ++j) { + SEXP col = params[j]; + if (Rf_length(col) != n) + stop("Parameter %i does not have length %d.", j + 1, n); + } + } } diff --git a/src/DbResult.h b/src/DbResult.h index dcc8e13c..96fb8ecb 100644 --- a/src/DbResult.h +++ b/src/DbResult.h @@ -13,32 +13,32 @@ typedef boost::shared_ptr DbConnectionPtr; // DbResult -------------------------------------------------------------------- class DbResult : boost::noncopyable { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - protected: - boost::scoped_ptr impl; +protected: + boost::scoped_ptr impl; - protected: - DbResult(const DbConnectionPtr& pConn); +protected: + DbResult(const DbConnectionPtr& pConn); - public: - ~DbResult(); +public: + ~DbResult(); - public: - void close(); +public: + void close(); - bool complete() const; - bool is_active() const; - int n_rows_fetched(); - int n_rows_affected(); + bool complete() const; + bool is_active() const; + int n_rows_fetched(); + int n_rows_affected(); - void bind(const List& params); - List fetch(int n_max = -1); + void bind(const List& params); + List fetch(int n_max = -1); - List get_column_info(); + List get_column_info(); - private: - void validate_params(const List& params) const; +private: + void validate_params(const List& params) const; }; #endif // __RDBI_DB_RESULT__ diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index af5c384f..e598429f 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -12,253 +12,253 @@ MariaBinding::~MariaBinding() { } void MariaBinding::setup(MYSQL_STMT* statement_) { - LOG_VERBOSE; + LOG_VERBOSE; - statement = statement_; - p = static_cast(mysql_stmt_param_count(statement)); + statement = statement_; + p = static_cast(mysql_stmt_param_count(statement)); - bindings.resize(p); - types.resize(p); - is_null.resize(p); - time_buffers.resize(p); + bindings.resize(p); + types.resize(p); + is_null.resize(p); + time_buffers.resize(p); } void MariaBinding::init_binding(const List& params_) { - LOG_VERBOSE; - - params = params_; - - if (params.size() == 0) { - stop("Query has no parameters"); - } - - if (p != params.size()) { - stop("Number of params don't match (%i vs %i)", p, params.size()); - } - - i = 0; - - for (int j = 0; j < p; ++j) { - RObject param(params[j]); - MariaFieldType type = variable_type_from_object(param); - types[j] = type; - - LOG_VERBOSE << j << " -> " << type_name(type); - - if (j == 0) { - n_rows = Rf_xlength(param); - } - - switch (type) { - case MY_LGL: - binding_update(j, MYSQL_TYPE_TINY, 1); - break; - case MY_INT32: - binding_update(j, MYSQL_TYPE_LONG, 4); - break; - case MY_DBL: - binding_update(j, MYSQL_TYPE_DOUBLE, 8); - break; - case MY_DATE: - binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); - break; - case MY_TIME: - binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); - break; - case MY_STR: - binding_update(j, MYSQL_TYPE_STRING, 0); - break; - case MY_RAW: - binding_update(j, MYSQL_TYPE_BLOB, 0); - break; - case MY_INT64: - binding_update(j, MYSQL_TYPE_LONGLONG, 0); - break; - } - } + LOG_VERBOSE; + + params = params_; + + if (params.size() == 0) { + stop("Query has no parameters"); + } + + if (p != params.size()) { + stop("Number of params don't match (%i vs %i)", p, params.size()); + } + + i = 0; + + for (int j = 0; j < p; ++j) { + RObject param(params[j]); + MariaFieldType type = variable_type_from_object(param); + types[j] = type; + + LOG_VERBOSE << j << " -> " << type_name(type); + + if (j == 0) { + n_rows = Rf_xlength(param); + } + + switch (type) { + case MY_LGL: + binding_update(j, MYSQL_TYPE_TINY, 1); + break; + case MY_INT32: + binding_update(j, MYSQL_TYPE_LONG, 4); + break; + case MY_DBL: + binding_update(j, MYSQL_TYPE_DOUBLE, 8); + break; + case MY_DATE: + binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); + break; + case MY_TIME: + binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); + break; + case MY_STR: + binding_update(j, MYSQL_TYPE_STRING, 0); + break; + case MY_RAW: + binding_update(j, MYSQL_TYPE_BLOB, 0); + break; + case MY_INT64: + binding_update(j, MYSQL_TYPE_LONGLONG, 0); + break; + } + } } bool MariaBinding::bind_next_row() { - LOG_VERBOSE; - - if (i >= n_rows) - return false; - - for (int j = 0; j < p; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types[j]); - - bool missing = false; - RObject col(params[j]); - - switch (types[j]) { - case MY_LGL: - if (LOGICAL(col)[i] == NA_LOGICAL) { - missing = true; - break; - } - bindings[j].buffer = &LOGICAL(col)[i]; - break; - case MY_INT32: - if (INTEGER(col)[i] == NA_INTEGER) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER(col)[i]; - break; - case MY_DBL: - if (ISNA(REAL(col)[i])) { - missing = true; - break; - } - bindings[j].buffer = &REAL(col)[i]; - break; - case MY_STR: - if (STRING_ELT(col, i) == NA_STRING) { - missing = true; - break; - } else { - SEXP string = STRING_ELT(col, i); - bindings[j].buffer = const_cast(CHAR(string)); - bindings[j].buffer_length = Rf_length(string); - } - break; - case MY_RAW: { - SEXP raw = VECTOR_ELT(col, i); - if (Rf_isNull(raw)) { - missing = true; - } else { - bindings[j].buffer_length = Rf_length(raw); - bindings[j].buffer = RAW(raw); - } - break; - } - case MY_DATE: - case MY_DATE_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - } else { - double val = REAL(col)[i]; - LOG_VERBOSE << val; - if (types[j] == MY_DATE) { - set_date_buffer(j, static_cast(::floor(val))); - clear_time_buffer(j); - } else { - double days = ::floor(val / 86400.0); - set_date_buffer(j, static_cast(days)); - set_time_buffer(j, val - days * 86400.0); - } - LOG_VERBOSE; - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - break; - } else { - double val = REAL(col)[i]; - clear_date_buffer(j); - set_time_buffer(j, val); - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_INT64: - if (INTEGER64(col)[i] == NA_INTEGER64) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER64(col)[i]; - break; - } - is_null[j] = missing; - } - - LOG_DEBUG << "Binding"; - mysql_stmt_bind_param(statement, &bindings[0]); - - LOG_DEBUG << "Done binding row " << i; - i++; - return true; + LOG_VERBOSE; + + if (i >= n_rows) + return false; + + for (int j = 0; j < p; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types[j]); + + bool missing = false; + RObject col(params[j]); + + switch (types[j]) { + case MY_LGL: + if (LOGICAL(col)[i] == NA_LOGICAL) { + missing = true; + break; + } + bindings[j].buffer = &LOGICAL(col)[i]; + break; + case MY_INT32: + if (INTEGER(col)[i] == NA_INTEGER) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER(col)[i]; + break; + case MY_DBL: + if (ISNA(REAL(col)[i])) { + missing = true; + break; + } + bindings[j].buffer = &REAL(col)[i]; + break; + case MY_STR: + if (STRING_ELT(col, i) == NA_STRING) { + missing = true; + break; + } else { + SEXP string = STRING_ELT(col, i); + bindings[j].buffer = const_cast(CHAR(string)); + bindings[j].buffer_length = Rf_length(string); + } + break; + case MY_RAW: { + SEXP raw = VECTOR_ELT(col, i); + if (Rf_isNull(raw)) { + missing = true; + } else { + bindings[j].buffer_length = Rf_length(raw); + bindings[j].buffer = RAW(raw); + } + break; + } + case MY_DATE: + case MY_DATE_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + } else { + double val = REAL(col)[i]; + LOG_VERBOSE << val; + if (types[j] == MY_DATE) { + set_date_buffer(j, static_cast(::floor(val))); + clear_time_buffer(j); + } else { + double days = ::floor(val / 86400.0); + set_date_buffer(j, static_cast(days)); + set_time_buffer(j, val - days * 86400.0); + } + LOG_VERBOSE; + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + break; + } else { + double val = REAL(col)[i]; + clear_date_buffer(j); + set_time_buffer(j, val); + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_INT64: + if (INTEGER64(col)[i] == NA_INTEGER64) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER64(col)[i]; + break; + } + is_null[j] = missing; + } + + LOG_DEBUG << "Binding"; + mysql_stmt_bind_param(statement, &bindings[0]); + + LOG_DEBUG << "Done binding row " << i; + i++; + return true; } void MariaBinding::binding_update(int j, enum_field_types type, int size) { - LOG_VERBOSE << j << ", " << type << ", " << size; + LOG_VERBOSE << j << ", " << type << ", " << size; - bindings[j].buffer_length = size; - bindings[j].buffer_type = type; - bindings[j].is_null = &is_null[j]; + bindings[j].buffer_length = size; + bindings[j].buffer_type = type; + bindings[j].is_null = &is_null[j]; } void MariaBinding::clear_date_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].year = 0; - time_buffers[j].month = 0; - time_buffers[j].day = 0; + LOG_VERBOSE << j; + time_buffers[j].year = 0; + time_buffers[j].month = 0; + time_buffers[j].day = 0; } void MariaBinding::set_date_buffer(int j, const int date) { - LOG_VERBOSE << date; - - // https://howardhinnant.github.io/date_algorithms.html#civil_from_days - const int date_0 = date + 719468; - const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; - const unsigned doe = - static_cast(date_0 - era * 146097); // [0, 146096] - LOG_VERBOSE << doe; - const unsigned yoe = - (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] - LOG_VERBOSE << yoe; - const int y = static_cast(yoe) + era * 400; - const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] - const unsigned mp = (5 * doy + 2) / 153; // [0, 11] - const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] - const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] - const unsigned yr = y + (m <= 2); - - // gmtime() fails for dates < 1970 on Windows - LOG_VERBOSE << date_0; - LOG_VERBOSE << yr; - LOG_VERBOSE << m; - LOG_VERBOSE << d; - - time_buffers[j].year = yr; - time_buffers[j].month = m; - time_buffers[j].day = d; + LOG_VERBOSE << date; + + // https://howardhinnant.github.io/date_algorithms.html#civil_from_days + const int date_0 = date + 719468; + const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; + const unsigned doe = + static_cast(date_0 - era * 146097); // [0, 146096] + LOG_VERBOSE << doe; + const unsigned yoe = + (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] + LOG_VERBOSE << yoe; + const int y = static_cast(yoe) + era * 400; + const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] + const unsigned mp = (5 * doy + 2) / 153; // [0, 11] + const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] + const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] + const unsigned yr = y + (m <= 2); + + // gmtime() fails for dates < 1970 on Windows + LOG_VERBOSE << date_0; + LOG_VERBOSE << yr; + LOG_VERBOSE << m; + LOG_VERBOSE << d; + + time_buffers[j].year = yr; + time_buffers[j].month = m; + time_buffers[j].day = d; } void MariaBinding::clear_time_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].hour = 0; - time_buffers[j].minute = 0; - time_buffers[j].second = 0; - time_buffers[j].second_part = 0; - time_buffers[j].neg = 0; + LOG_VERBOSE << j; + time_buffers[j].hour = 0; + time_buffers[j].minute = 0; + time_buffers[j].second = 0; + time_buffers[j].second_part = 0; + time_buffers[j].neg = 0; } void MariaBinding::set_time_buffer(int j, double time) { - LOG_VERBOSE << time; - - bool neg = false; - if (time < 0) { - neg = true; - time = -time; - } - double whole_seconds = ::trunc(time); - double frac_seconds = time - whole_seconds; - double whole_minutes = ::trunc(time / 60.0); - double seconds = whole_seconds - whole_minutes * 60.0; - double hours = ::trunc(time / 3600.0); - double minutes = whole_minutes - hours * 60.0; - - time_buffers[j].hour = static_cast(hours); - time_buffers[j].minute = static_cast(minutes); - time_buffers[j].second = static_cast(seconds); - time_buffers[j].second_part = - static_cast(frac_seconds * 1000000.0); - time_buffers[j].neg = neg; + LOG_VERBOSE << time; + + bool neg = false; + if (time < 0) { + neg = true; + time = -time; + } + double whole_seconds = ::trunc(time); + double frac_seconds = time - whole_seconds; + double whole_minutes = ::trunc(time / 60.0); + double seconds = whole_seconds - whole_minutes * 60.0; + double hours = ::trunc(time / 3600.0); + double minutes = whole_minutes - hours * 60.0; + + time_buffers[j].hour = static_cast(hours); + time_buffers[j].minute = static_cast(minutes); + time_buffers[j].second = static_cast(seconds); + time_buffers[j].second_part = + static_cast(frac_seconds * 1000000.0); + time_buffers[j].neg = neg; } diff --git a/src/MariaBinding.h b/src/MariaBinding.h index 9a7173ed..e66bd096 100644 --- a/src/MariaBinding.h +++ b/src/MariaBinding.h @@ -7,33 +7,33 @@ #include "MariaTypes.h" class MariaBinding : public boost::noncopyable { - MYSQL_STMT* statement; - List params; + MYSQL_STMT* statement; + List params; - int p; - R_xlen_t i, n_rows; - std::vector bindings; - boost::container::vector is_null; - std::vector types; - std::vector time_buffers; + int p; + R_xlen_t i, n_rows; + std::vector bindings; + boost::container::vector is_null; + std::vector types; + std::vector time_buffers; - public: - MariaBinding(); - ~MariaBinding(); +public: + MariaBinding(); + ~MariaBinding(); - public: - void setup(MYSQL_STMT* statement_); +public: + void setup(MYSQL_STMT* statement_); - void init_binding(const List& params); - bool bind_next_row(); + void init_binding(const List& params); + bool bind_next_row(); - private: - void binding_update(int j, enum_field_types type, int size); +private: + void binding_update(int j, enum_field_types type, int size); - void clear_date_buffer(int j); - void set_date_buffer(int j, int date); - void clear_time_buffer(int j); - void set_time_buffer(int j, double time); + void clear_date_buffer(int j); + void set_date_buffer(int j, int date); + void clear_time_buffer(int j); + void set_time_buffer(int j, double time); }; #endif diff --git a/src/MariaResult.cpp b/src/MariaResult.cpp index f3031f80..a25e20de 100644 --- a/src/MariaResult.cpp +++ b/src/MariaResult.cpp @@ -9,24 +9,25 @@ MariaResult::MariaResult(const DbConnectionPtr& pConn, const std::string& sql, bool is_statement) : DbResult(pConn) { - boost::scoped_ptr res( - new MariaResultPrep(pConn, is_statement)); - try { - res->send_query(sql); - } catch (const MariaResultPrep::UnsupportedPS& e) { - res.reset(NULL); - // is_statement info might be worthwhile to pass to simple queries as well - res.reset(new MariaResultSimple(pConn, is_statement)); - res->send_query(sql); - } + boost::scoped_ptr res( + new MariaResultPrep(pConn, is_statement)); + try { + res->send_query(sql); + } catch (const MariaResultPrep::UnsupportedPS& e) { + res.reset(NULL); + // is_statement info might be worthwhile to pass to simple queries as + // well + res.reset(new MariaResultSimple(pConn, is_statement)); + res->send_query(sql); + } - res.swap(impl); + res.swap(impl); } DbResult* MariaResult::create_and_send_query(const DbConnectionPtr& con, const std::string& sql, bool is_statement) { - return new MariaResult(con, sql, is_statement); + return new MariaResult(con, sql, is_statement); } // Publics ///////////////////////////////////////////////////////////////////// diff --git a/src/MariaResult.h b/src/MariaResult.h index 3e4f5950..6835fe38 100644 --- a/src/MariaResult.h +++ b/src/MariaResult.h @@ -6,17 +6,17 @@ // MariaResult ----------------------------------------------------------------- class MariaResult : public DbResult { - protected: - MariaResult(const DbConnectionPtr& pConn, const std::string& sql, - bool is_statement); +protected: + MariaResult(const DbConnectionPtr& pConn, const std::string& sql, + bool is_statement); - public: - static DbResult* create_and_send_query(const DbConnectionPtr& con, - const std::string& sql, - bool is_statement); +public: + static DbResult* create_and_send_query(const DbConnectionPtr& con, + const std::string& sql, + bool is_statement); - public: - void close(); +public: + void close(); }; #endif // __RMARIADB_MARIA_RESULT__ diff --git a/src/MariaResultImpl.h b/src/MariaResultImpl.h index 8eb2acd4..1bf2791c 100644 --- a/src/MariaResultImpl.h +++ b/src/MariaResultImpl.h @@ -2,23 +2,23 @@ #define RMARIADB_MARIARESULTIMPL_H class MariaResultImpl { - public: - MariaResultImpl(); - virtual ~MariaResultImpl(); +public: + MariaResultImpl(); + virtual ~MariaResultImpl(); - public: - virtual void send_query(const std::string& sql) = 0; - virtual void close() = 0; +public: + virtual void send_query(const std::string& sql) = 0; + virtual void close() = 0; - virtual void bind(const List& params) = 0; + virtual void bind(const List& params) = 0; - virtual List get_column_info() = 0; + virtual List get_column_info() = 0; - virtual List fetch(int n_max = -1) = 0; + virtual List fetch(int n_max = -1) = 0; - virtual int n_rows_affected() = 0; - virtual int n_rows_fetched() = 0; - virtual bool complete() const = 0; + virtual int n_rows_affected() = 0; + virtual int n_rows_fetched() = 0; + virtual bool complete() const = 0; }; #endif // RMARIADB_MARIARESULTIMPL_H diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index dafc4d28..7299e08f 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -18,247 +18,249 @@ MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, bound_(false), complete_(false), is_statement_(is_statement) { - pStatement_ = mysql_stmt_init(pConn_->get_conn()); - if (pStatement_ == NULL) - stop("Out of memory"); + pStatement_ = mysql_stmt_init(pConn_->get_conn()); + if (pStatement_ == NULL) + stop("Out of memory"); } MariaResultPrep::~MariaResultPrep() { - MariaResultPrep::close(); + MariaResultPrep::close(); } void MariaResultPrep::send_query(const std::string& sql) { - LOG_DEBUG << sql; - - LOG_DEBUG << "mysql_stmt_prepare()"; - if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { - if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { - throw UnsupportedPS(); - } - - throw_error(); - } - - nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); - LOG_DEBUG << nParams_; - - // Need to set pSpec_ before calling execute() - pSpec_ = mysql_stmt_result_metadata(pStatement_); - - if (nParams_ == 0) { - // Not parameterised so we can execute immediately - execute(); - bound_ = true; - } - - if (has_result()) { - // Query returns results, so cache column names and types - cache_metadata(); - bindingOutput_.setup(pStatement_, types_); - } + LOG_DEBUG << sql; + + LOG_DEBUG << "mysql_stmt_prepare()"; + if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { + if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { + throw UnsupportedPS(); + } + + throw_error(); + } + + nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); + LOG_DEBUG << nParams_; + + // Need to set pSpec_ before calling execute() + pSpec_ = mysql_stmt_result_metadata(pStatement_); + + if (nParams_ == 0) { + // Not parameterised so we can execute immediately + execute(); + bound_ = true; + } + + if (has_result()) { + // Query returns results, so cache column names and types + cache_metadata(); + bindingOutput_.setup(pStatement_, types_); + } } void MariaResultPrep::close() { - if (has_result()) { - mysql_free_result(pSpec_); - pSpec_ = NULL; - } + if (has_result()) { + mysql_free_result(pSpec_); + pSpec_ = NULL; + } - if (pStatement_ != NULL) { - mysql_stmt_close(pStatement_); - pStatement_ = NULL; - } + if (pStatement_ != NULL) { + mysql_stmt_close(pStatement_); + pStatement_ = NULL; + } - pConn_->autocommit(); + pConn_->autocommit(); } void MariaResultPrep::execute() { - LOG_VERBOSE; - - complete_ = false; - - LOG_DEBUG << "mysql_stmt_execute()"; - if (mysql_stmt_execute(pStatement_) != 0) { - LOG_VERBOSE; - throw_error(); - } - LOG_VERBOSE << "has_result()"; - if (!has_result() && !is_statement_) { - LOG_VERBOSE; - // try again after mysql_stmt_execute, in case pSpec_ == NULL - pSpec_ = mysql_stmt_result_metadata(pStatement_); - } - if (!has_result()) { - LOG_VERBOSE; - rowsAffected_ += mysql_stmt_affected_rows(pStatement_); - } + LOG_VERBOSE; + + complete_ = false; + + LOG_DEBUG << "mysql_stmt_execute()"; + if (mysql_stmt_execute(pStatement_) != 0) { + LOG_VERBOSE; + throw_error(); + } + LOG_VERBOSE << "has_result()"; + if (!has_result() && !is_statement_) { + LOG_VERBOSE; + // try again after mysql_stmt_execute, in case pSpec_ == NULL + pSpec_ = mysql_stmt_result_metadata(pStatement_); + } + if (!has_result()) { + LOG_VERBOSE; + rowsAffected_ += mysql_stmt_affected_rows(pStatement_); + } } void MariaResultPrep::bind(const List& params) { - rowsAffected_ = 0; + rowsAffected_ = 0; - bindingInput_.setup(pStatement_); - bindingInput_.init_binding(params); + bindingInput_.setup(pStatement_); + bindingInput_.init_binding(params); - if (has_result()) { - complete_ = true; - } else { - while (bindingInput_.bind_next_row()) { - execute(); - } - } + if (has_result()) { + complete_ = true; + } else { + while (bindingInput_.bind_next_row()) { + execute(); + } + } - bound_ = true; + bound_ = true; } List MariaResultPrep::get_column_info() { - CharacterVector names(nCols_), types(nCols_); - for (int i = 0; i < nCols_; i++) { - names[i] = names_[i]; - types[i] = type_name(types_[i]); - } + CharacterVector names(nCols_), types(nCols_); + for (int i = 0; i < nCols_; i++) { + names[i] = names_[i]; + types[i] = type_name(types_[i]); + } - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } bool MariaResultPrep::has_result() const { - return pSpec_ != NULL; + return pSpec_ != NULL; } bool MariaResultPrep::step() { - LOG_VERBOSE; + LOG_VERBOSE; - while (!fetch_row()) { - LOG_VERBOSE; + while (!fetch_row()) { + LOG_VERBOSE; - if (!bindingInput_.bind_next_row()) - return false; - execute(); - } + if (!bindingInput_.bind_next_row()) + return false; + execute(); + } - rowsFetched_++; + rowsFetched_++; - LOG_VERBOSE << rowsFetched_; - return true; + LOG_VERBOSE << rowsFetched_; + return true; } bool MariaResultPrep::fetch_row() { - LOG_VERBOSE; - - if (complete_) - return false; - - LOG_VERBOSE << "mysql_stmt_fetch()"; - int result = mysql_stmt_fetch(pStatement_); - - LOG_VERBOSE << result; - - switch (result) { - // We expect truncation whenever there's a string or blob - case MYSQL_DATA_TRUNCATED: - case 0: - return true; - case 1: - throw_error(); - case MYSQL_NO_DATA: - complete_ = true; - return false; - } - return false; + LOG_VERBOSE; + + if (complete_) + return false; + + LOG_VERBOSE << "mysql_stmt_fetch()"; + int result = mysql_stmt_fetch(pStatement_); + + LOG_VERBOSE << result; + + switch (result) { + // We expect truncation whenever there's a string or blob + case MYSQL_DATA_TRUNCATED: + case 0: + return true; + case 1: + throw_error(); + case MYSQL_NO_DATA: + complete_ = true; + return false; + } + return false; } List MariaResultPrep::fetch(int n_max) { - if (!bound_) - stop("Query needs to be bound before fetching"); - if (!has_result()) { - if (names_.size() == 0) { - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and also " - "avoid dbFetch()"); - } - return df_create(types_, names_, 0); - } - - int n = (n_max < 0) ? 100 : n_max; - List out = df_create(types_, names_, n); - if (n == 0) - return out; - - int i = 0; - - for (;;) { - if (i >= n && n_max > 0) - break; - - if (!step()) - break; - - if (i >= n) { - n *= 2; - out = df_resize(out, n); - } - - for (int j = 0; j < nCols_; ++j) { - // Rcout << i << "," << j << "\n"; - bindingOutput_.set_list_value(out[j], i, j); - } - - ++i; - if (i % 1024 == 0) - checkUserInterrupt(); - } - - // Trim back to what we actually used - if (i < n) { - out = df_resize(out, i); - } - // Set up S3 classes - df_s3(out, types_); - - return out; + if (!bound_) + stop("Query needs to be bound before fetching"); + if (!has_result()) { + if (names_.size() == 0) { + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and " + "also " + "avoid dbFetch()"); + } + return df_create(types_, names_, 0); + } + + int n = (n_max < 0) ? 100 : n_max; + List out = df_create(types_, names_, n); + if (n == 0) + return out; + + int i = 0; + + for (;;) { + if (i >= n && n_max > 0) + break; + + if (!step()) + break; + + if (i >= n) { + n *= 2; + out = df_resize(out, n); + } + + for (int j = 0; j < nCols_; ++j) { + // Rcout << i << "," << j << "\n"; + bindingOutput_.set_list_value(out[j], i, j); + } + + ++i; + if (i % 1024 == 0) + checkUserInterrupt(); + } + + // Trim back to what we actually used + if (i < n) { + out = df_resize(out, i); + } + // Set up S3 classes + df_s3(out, types_); + + return out; } int MariaResultPrep::n_rows_affected() { - if (!bound_) - return NA_INTEGER; - // FIXME: > 2^32 rows? - return static_cast(rowsAffected_); + if (!bound_) + return NA_INTEGER; + // FIXME: > 2^32 rows? + return static_cast(rowsAffected_); } int MariaResultPrep::n_rows_fetched() { - if (!bound_) - return 0; - // FIXME: > 2^32 rows? - return static_cast(rowsFetched_); + if (!bound_) + return 0; + // FIXME: > 2^32 rows? + return static_cast(rowsFetched_); } bool MariaResultPrep::complete() const { - if (!bound_) - return FALSE; - return !has_result() || // query doesn't have results - complete_; // we've fetched all available results + if (!bound_) + return FALSE; + return !has_result() || // query doesn't have results + complete_; // we've fetched all available results } void MariaResultPrep::throw_error() { - stop("%s [%i]", mysql_stmt_error(pStatement_), mysql_stmt_errno(pStatement_)); + stop("%s [%i]", mysql_stmt_error(pStatement_), + mysql_stmt_errno(pStatement_)); } void MariaResultPrep::cache_metadata() { - LOG_VERBOSE; + LOG_VERBOSE; - nCols_ = mysql_num_fields(pSpec_); - MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); + nCols_ = mysql_num_fields(pSpec_); + MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); - for (int i = 0; i < nCols_; ++i) { - names_.push_back(fields[i].name); + for (int i = 0; i < nCols_; ++i) { + names_.push_back(fields[i].name); - bool binary = fields[i].charsetnr == 63; - bool length1 = fields[i].length == 1; - MariaFieldType type = - variable_type_from_field_type(fields[i].type, binary, length1); - types_.push_back(type); + bool binary = fields[i].charsetnr == 63; + bool length1 = fields[i].length == 1; + MariaFieldType type = + variable_type_from_field_type(fields[i].type, binary, length1); + types_.push_back(type); - LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type - << ", " << binary << ") => " << type_name(type); - } + LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type + << ", " << binary << ") => " << type_name(type); + } } diff --git a/src/MariaResultPrep.h b/src/MariaResultPrep.h index 9c55af9c..f07ef302 100644 --- a/src/MariaResultPrep.h +++ b/src/MariaResultPrep.h @@ -14,52 +14,52 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultPrep : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - MYSQL_STMT* pStatement_; - MYSQL_RES* pSpec_; - uint64_t rowsAffected_, rowsFetched_; + MYSQL_STMT* pStatement_; + MYSQL_RES* pSpec_; + uint64_t rowsAffected_, rowsFetched_; - int nCols_, nParams_; - bool bound_, complete_; - bool is_statement_; + int nCols_, nParams_; + bool bound_, complete_; + bool is_statement_; - std::vector types_; - std::vector names_; - MariaBinding bindingInput_; - MariaRow bindingOutput_; + std::vector types_; + std::vector names_; + MariaBinding bindingInput_; + MariaRow bindingOutput_; - public: - MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); - ~MariaResultPrep(); +public: + MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); + ~MariaResultPrep(); - public: - virtual void send_query(const std::string& sql); - virtual void close(); +public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; - public: - class UnsupportedPS : public std::exception {}; +public: + class UnsupportedPS : public std::exception {}; - private: - void execute(); +private: + void execute(); - bool has_result() const; - bool step(); - bool fetch_row(); - void NORET throw_error(); + bool has_result() const; + bool step(); + bool fetch_row(); + void NORET throw_error(); - private: - void cache_metadata(); +private: + void cache_metadata(); }; #endif diff --git a/src/MariaResultSimple.cpp b/src/MariaResultSimple.cpp index cb27c135..1ffaebc0 100644 --- a/src/MariaResultSimple.cpp +++ b/src/MariaResultSimple.cpp @@ -6,59 +6,60 @@ MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement) : pConn_(pConn) { - (void)is_statement; + (void)is_statement; } MariaResultSimple::~MariaResultSimple() { - MariaResultSimple::close(); + MariaResultSimple::close(); } void MariaResultSimple::send_query(const std::string& sql) { - LOG_DEBUG << sql; + LOG_DEBUG << sql; - exec(sql); + exec(sql); } void MariaResultSimple::close() { - LOG_VERBOSE; + LOG_VERBOSE; } void MariaResultSimple::bind(const List& /*params*/) { - LOG_VERBOSE; + LOG_VERBOSE; - stop( - "This query is not supported by the prepared statement protocol, no " - "parameters can be bound."); + stop( + "This query is not supported by the prepared statement protocol, no " + "parameters can be bound."); } List MariaResultSimple::get_column_info() { - CharacterVector names(0), types(0); + CharacterVector names(0), types(0); - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } List MariaResultSimple::fetch(int /*n_max*/) { - LOG_VERBOSE; - - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and also avoid " - "dbFetch()"); - return df_create(std::vector(), std::vector(), - 0); + LOG_VERBOSE; + + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and also " + "avoid " + "dbFetch()"); + return df_create(std::vector(), std::vector(), + 0); } int MariaResultSimple::n_rows_affected() { - return 0; + return 0; } int MariaResultSimple::n_rows_fetched() { - return 0; + return 0; } bool MariaResultSimple::complete() const { - return true; + return true; } void MariaResultSimple::exec(const std::string& sql) { - pConn_->exec(sql); + pConn_->exec(sql); } diff --git a/src/MariaResultSimple.h b/src/MariaResultSimple.h index 329e62d7..9cf0f846 100644 --- a/src/MariaResultSimple.h +++ b/src/MariaResultSimple.h @@ -14,28 +14,28 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultSimple : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - public: - MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); - ~MariaResultSimple(); +public: + MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); + ~MariaResultSimple(); - public: - virtual void send_query(const std::string& sql); - virtual void close(); +public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; - private: - void exec(const std::string& sql); +private: + void exec(const std::string& sql); }; #endif diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index 06ca8074..d9730832 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -13,245 +13,245 @@ MariaRow::~MariaRow() { void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& types) { - LOG_VERBOSE; - - pStatement_ = pStatement; - types_ = types; - n_ = static_cast(types_.size()); - - bindings_.resize(n_); - buffers_.resize(n_); - lengths_.resize(n_); - nulls_.resize(n_); - errors_.resize(n_); - - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types_[j]); - - // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html - switch (types_[j]) { - case MY_INT32: - bindings_[j].buffer_type = MYSQL_TYPE_LONG; - buffers_[j].resize(4); - break; - case MY_INT64: - bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; - buffers_[j].resize(8); - break; - case MY_DBL: - bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; - buffers_[j].resize(8); - break; - case MY_DATE: - bindings_[j].buffer_type = MYSQL_TYPE_DATE; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_TIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_STR: - bindings_[j].buffer_type = MYSQL_TYPE_STRING; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_RAW: - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_LGL: - // BIT(1) is bound to logical, in absence of dedicated type - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(4); - break; - } - - lengths_[j] = buffers_[j].size(); - bindings_[j].buffer_length = buffers_[j].size(); - if (bindings_[j].buffer_length > 0) - bindings_[j].buffer = &buffers_[j][0]; - else - bindings_[j].buffer = NULL; - bindings_[j].length = &lengths_[j]; - bindings_[j].is_null = &nulls_[j]; - bindings_[j].is_unsigned = true; - bindings_[j].error = &errors_[j]; - - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; - } - - LOG_DEBUG << "mysql_stmt_bind_result()"; - if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { - stop("Error binding result: %s", mysql_stmt_error(pStatement)); - } - - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; - } + LOG_VERBOSE; + + pStatement_ = pStatement; + types_ = types; + n_ = static_cast(types_.size()); + + bindings_.resize(n_); + buffers_.resize(n_); + lengths_.resize(n_); + nulls_.resize(n_); + errors_.resize(n_); + + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types_[j]); + + // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html + switch (types_[j]) { + case MY_INT32: + bindings_[j].buffer_type = MYSQL_TYPE_LONG; + buffers_[j].resize(4); + break; + case MY_INT64: + bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; + buffers_[j].resize(8); + break; + case MY_DBL: + bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; + buffers_[j].resize(8); + break; + case MY_DATE: + bindings_[j].buffer_type = MYSQL_TYPE_DATE; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_TIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_STR: + bindings_[j].buffer_type = MYSQL_TYPE_STRING; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_RAW: + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_LGL: + // BIT(1) is bound to logical, in absence of dedicated type + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(4); + break; + } + + lengths_[j] = buffers_[j].size(); + bindings_[j].buffer_length = buffers_[j].size(); + if (bindings_[j].buffer_length > 0) + bindings_[j].buffer = &buffers_[j][0]; + else + bindings_[j].buffer = NULL; + bindings_[j].length = &lengths_[j]; + bindings_[j].is_null = &nulls_[j]; + bindings_[j].is_unsigned = true; + bindings_[j].error = &errors_[j]; + + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; + } + + LOG_DEBUG << "mysql_stmt_bind_result()"; + if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { + stop("Error binding result: %s", mysql_stmt_error(pStatement)); + } + + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; + } } bool MariaRow::is_null(int j) { - return nulls_[j] == 1; + return nulls_[j] == 1; } int MariaRow::value_bool(int j) { - if (is_null(j)) { - return NA_LOGICAL; - } else { - return static_cast(value_int(j) == 1); - } + if (is_null(j)) { + return NA_LOGICAL; + } else { + return static_cast(value_int(j) == 1); + } } int MariaRow::value_int(int j) { - return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); } int64_t MariaRow::value_int64(int j) { - return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); } double MariaRow::value_double(int j) { - return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); + return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); } SEXP MariaRow::value_string(int j) { - if (is_null(j)) - return NA_STRING; + if (is_null(j)) + return NA_STRING; - fetch_buffer(j); - int len = static_cast(buffers_[j].size()); - if (len == 0) - return R_BlankString; + fetch_buffer(j); + int len = static_cast(buffers_[j].size()); + if (len == 0) + return R_BlankString; - const char* val = reinterpret_cast(&buffers_[j][0]); - return Rf_mkCharLenCE(val, len, CE_UTF8); + const char* val = reinterpret_cast(&buffers_[j][0]); + return Rf_mkCharLenCE(val, len, CE_UTF8); } SEXP MariaRow::value_raw(int j) { - if (is_null(j)) - return R_NilValue; + if (is_null(j)) + return R_NilValue; - fetch_buffer(j); - SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); - memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); + fetch_buffer(j); + SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); + memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); - return bytes; + return bytes; } double MariaRow::value_date_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days) * 86400.0 + - static_cast(mytime->hour) * (60.0 * 60) + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; - LOG_VERBOSE << date_time; - return date_time; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days) * 86400.0 + + static_cast(mytime->hour) * (60.0 * 60) + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_date(int j) { - if (is_null(j)) - return NA_REAL; + if (is_null(j)) + return NA_REAL; - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days); - LOG_VERBOSE << date_time; - return date_time; + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days); + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - return static_cast(mytime->hour) * 3600.0 + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + return static_cast(mytime->hour) * 3600.0 + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; } void MariaRow::set_list_value(SEXP x, int i, int j) { - switch (types_[j]) { - case MY_INT32: - INTEGER(x)[i] = value_int(j); - break; - case MY_INT64: - INTEGER64(x)[i] = value_int64(j); - break; - case MY_DBL: - REAL(x)[i] = value_double(j); - break; - case MY_DATE: - REAL(x)[i] = value_date(j); - break; - case MY_DATE_TIME: - REAL(x)[i] = value_date_time(j); - break; - case MY_TIME: - REAL(x)[i] = value_time(j); - break; - case MY_STR: - SET_STRING_ELT(x, i, value_string(j)); - break; - case MY_RAW: - SET_VECTOR_ELT(x, i, value_raw(j)); - break; - case MY_LGL: - LOGICAL(x)[i] = value_bool(j); - break; - } + switch (types_[j]) { + case MY_INT32: + INTEGER(x)[i] = value_int(j); + break; + case MY_INT64: + INTEGER64(x)[i] = value_int64(j); + break; + case MY_DBL: + REAL(x)[i] = value_double(j); + break; + case MY_DATE: + REAL(x)[i] = value_date(j); + break; + case MY_DATE_TIME: + REAL(x)[i] = value_date_time(j); + break; + case MY_TIME: + REAL(x)[i] = value_time(j); + break; + case MY_STR: + SET_STRING_ELT(x, i, value_string(j)); + break; + case MY_RAW: + SET_VECTOR_ELT(x, i, value_raw(j)); + break; + case MY_LGL: + LOGICAL(x)[i] = value_bool(j); + break; + } } void MariaRow::fetch_buffer(int j) { - unsigned long length = lengths_[j]; - LOG_VERBOSE << length; + unsigned long length = lengths_[j]; + LOG_VERBOSE << length; - buffers_[j].resize(length); - if (length == 0) - return; + buffers_[j].resize(length); + if (length == 0) + return; - bindings_[j].buffer = &buffers_[j][0]; // might have moved - bindings_[j].buffer_length = length; + bindings_[j].buffer = &buffers_[j][0]; // might have moved + bindings_[j].buffer_length = length; - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; - LOG_DEBUG << "mysql_stmt_fetch_column()"; - int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); - LOG_VERBOSE << result; + LOG_DEBUG << "mysql_stmt_fetch_column()"; + int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); + LOG_VERBOSE << result; - if (result != 0) - stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); + if (result != 0) + stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); - // Reset buffer length to zero for next row - bindings_[j].buffer = NULL; - bindings_[j].buffer_length = 0; + // Reset buffer length to zero for next row + bindings_[j].buffer = NULL; + bindings_[j].buffer_length = 0; } diff --git a/src/MariaRow.h b/src/MariaRow.h index d2a31e9b..553edd02 100644 --- a/src/MariaRow.h +++ b/src/MariaRow.h @@ -8,39 +8,41 @@ #include "MariaTypes.h" class MariaRow : public boost::noncopyable { - MYSQL_STMT* pStatement_; - - int n_; - std::vector bindings_; - - std::vector types_; - std::vector > buffers_; - std::vector lengths_; - boost::container::vector nulls_, errors_; - - public: - MariaRow(); - ~MariaRow(); - - public: - void setup(MYSQL_STMT* pStatement, const std::vector& types); - void set_list_value(SEXP x, int i, int j); - - private: - // Value accessors ----------------------------------------------------------- - bool is_null(int j); - - int value_int(int j); - int value_bool(int j); - int64_t value_int64(int j); - double value_double(int j); - SEXP value_string(int j); - SEXP value_raw(int j); - double value_date_time(int j); - double value_date(int j); - double value_time(int j); - - void fetch_buffer(int j); + MYSQL_STMT* pStatement_; + + int n_; + std::vector bindings_; + + std::vector types_; + std::vector > buffers_; + std::vector lengths_; + boost::container::vector nulls_, errors_; + +public: + MariaRow(); + ~MariaRow(); + +public: + void setup(MYSQL_STMT* pStatement, + const std::vector& types); + void set_list_value(SEXP x, int i, int j); + +private: + // Value accessors + // ----------------------------------------------------------- + bool is_null(int j); + + int value_int(int j); + int value_bool(int j); + int64_t value_int64(int j); + double value_double(int j); + SEXP value_string(int j); + SEXP value_raw(int j); + double value_date_time(int j); + double value_date(int j); + double value_time(int j); + + void fetch_buffer(int j); }; #endif diff --git a/src/MariaTypes.cpp b/src/MariaTypes.cpp index f381840f..ad420276 100644 --- a/src/MariaTypes.cpp +++ b/src/MariaTypes.cpp @@ -7,157 +7,157 @@ bool all_raw(SEXP x); MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, bool length1) { - switch (type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_YEAR: - return MY_INT32; + switch (type) { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_YEAR: + return MY_INT32; - case MYSQL_TYPE_LONGLONG: - return MY_INT64; + case MYSQL_TYPE_LONGLONG: + return MY_INT64; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - return MY_DBL; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - return MY_DATE_TIME; - case MYSQL_TYPE_DATE: - return MY_DATE; - case MYSQL_TYPE_TIME: - return MY_TIME; - case MYSQL_TYPE_BIT: - if (length1) { - return MY_LGL; - } - // fallthrough - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_SET: - return MY_STR; - case MYSQL_TYPE_GEOMETRY: - return MY_RAW; - case MYSQL_TYPE_NULL: - return MY_INT32; - default: - throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); - } + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + return MY_DBL; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_NEWDATE: + return MY_DATE_TIME; + case MYSQL_TYPE_DATE: + return MY_DATE; + case MYSQL_TYPE_TIME: + return MY_TIME; + case MYSQL_TYPE_BIT: + if (length1) { + return MY_LGL; + } + // fallthrough + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_SET: + return MY_STR; + case MYSQL_TYPE_GEOMETRY: + return MY_RAW; + case MYSQL_TYPE_NULL: + return MY_INT32; + default: + throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); + } } std::string type_name(MariaFieldType type) { - switch (type) { - case MY_INT32: - return "integer"; - case MY_INT64: - return "integer64"; - case MY_DBL: - return "double"; - case MY_STR: - return "string"; - case MY_DATE: - return "Date"; - case MY_DATE_TIME: - return "POSIXct"; - case MY_TIME: - return "hms"; - case MY_RAW: - return "raw"; - case MY_LGL: - return "logical"; - } - throw std::runtime_error("Invalid typeName"); + switch (type) { + case MY_INT32: + return "integer"; + case MY_INT64: + return "integer64"; + case MY_DBL: + return "double"; + case MY_STR: + return "string"; + case MY_DATE: + return "Date"; + case MY_DATE_TIME: + return "POSIXct"; + case MY_TIME: + return "hms"; + case MY_RAW: + return "raw"; + case MY_LGL: + return "logical"; + } + throw std::runtime_error("Invalid typeName"); } SEXPTYPE type_sexp(MariaFieldType type) { - switch (type) { - case MY_INT32: - return INTSXP; - case MY_INT64: - return INT64SXP; - case MY_DBL: - return REALSXP; - case MY_STR: - return STRSXP; - case MY_DATE: - return REALSXP; - case MY_DATE_TIME: - return REALSXP; - case MY_TIME: - return REALSXP; - case MY_RAW: - return VECSXP; - case MY_LGL: - return LGLSXP; - } - throw std::runtime_error("Invalid typeSEXP"); + switch (type) { + case MY_INT32: + return INTSXP; + case MY_INT64: + return INT64SXP; + case MY_DBL: + return REALSXP; + case MY_STR: + return STRSXP; + case MY_DATE: + return REALSXP; + case MY_DATE_TIME: + return REALSXP; + case MY_TIME: + return REALSXP; + case MY_RAW: + return VECSXP; + case MY_LGL: + return LGLSXP; + } + throw std::runtime_error("Invalid typeSEXP"); } std::string r_class(RObject x) { - RObject klass_(x.attr("class")); - std::string klass; - if (klass_ == R_NilValue) - return ""; + RObject klass_(x.attr("class")); + std::string klass; + if (klass_ == R_NilValue) + return ""; - CharacterVector klassv = as(klass_); - return std::string(klassv[klassv.length() - 1]); + CharacterVector klassv = as(klass_); + return std::string(klassv[klassv.length() - 1]); } MariaFieldType variable_type_from_object(const RObject& type) { - std::string klass = r_class(type); + std::string klass = r_class(type); - switch (TYPEOF(type)) { - case LGLSXP: - return MY_LGL; - case INTSXP: - return MY_INT32; - case REALSXP: - if (klass == "Date") - return MY_DATE; - if (klass == "POSIXt") - return MY_DATE_TIME; - if (klass == "difftime") - return MY_TIME; - if (klass == "integer64") - return MY_INT64; - return MY_DBL; - case STRSXP: - return MY_STR; - case VECSXP: - if (klass == "blob") - return MY_RAW; - if (all_raw(type)) - return MY_RAW; - break; - } + switch (TYPEOF(type)) { + case LGLSXP: + return MY_LGL; + case INTSXP: + return MY_INT32; + case REALSXP: + if (klass == "Date") + return MY_DATE; + if (klass == "POSIXt") + return MY_DATE_TIME; + if (klass == "difftime") + return MY_TIME; + if (klass == "integer64") + return MY_INT64; + return MY_DBL; + case STRSXP: + return MY_STR; + case VECSXP: + if (klass == "blob") + return MY_RAW; + if (all_raw(type)) + return MY_RAW; + break; + } - stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); - return MY_STR; + stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); + return MY_STR; } bool all_raw(SEXP x) { - List xx(x); - for (R_xlen_t i = 0; i < xx.length(); ++i) { - switch (TYPEOF(xx[i])) { - case RAWSXP: - case NILSXP: - break; + List xx(x); + for (R_xlen_t i = 0; i < xx.length(); ++i) { + switch (TYPEOF(xx[i])) { + case RAWSXP: + case NILSXP: + break; - default: - return false; - } - } - return true; + default: + return false; + } + } + return true; } diff --git a/src/MariaTypes.h b/src/MariaTypes.h index df681f7f..8d3fd866 100644 --- a/src/MariaTypes.h +++ b/src/MariaTypes.h @@ -2,15 +2,15 @@ #define __RMARIADB_MARIA_TYPES__ enum MariaFieldType { - MY_INT32, - MY_INT64, // output only - MY_DBL, - MY_STR, - MY_DATE, - MY_DATE_TIME, - MY_TIME, - MY_RAW, - MY_LGL // for BIT(1) + MY_INT32, + MY_INT64, // output only + MY_DBL, + MY_STR, + MY_DATE, + MY_DATE_TIME, + MY_TIME, + MY_RAW, + MY_LGL // for BIT(1) }; MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index d772fcae..0aae55fc 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -29,270 +29,271 @@ RcppExport SEXP _RMariaDB_connection_create( SEXP default_fileSEXP, SEXP ssl_keySEXP, SEXP ssl_certSEXP, SEXP ssl_caSEXP, SEXP ssl_capathSEXP, SEXP ssl_cipherSEXP, SEXP timeoutSEXP, SEXP reconnectSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter&>::type host( - hostSEXP); - Rcpp::traits::input_parameter&>::type user( - userSEXP); - Rcpp::traits::input_parameter&>::type password( - passwordSEXP); - Rcpp::traits::input_parameter&>::type db(dbSEXP); - Rcpp::traits::input_parameter::type port(portSEXP); - Rcpp::traits::input_parameter&>::type unix_socket( - unix_socketSEXP); - Rcpp::traits::input_parameter::type client_flag( - client_flagSEXP); - Rcpp::traits::input_parameter&>::type groups( - groupsSEXP); - Rcpp::traits::input_parameter&>::type - default_file(default_fileSEXP); - Rcpp::traits::input_parameter&>::type ssl_key( - ssl_keySEXP); - Rcpp::traits::input_parameter&>::type ssl_cert( - ssl_certSEXP); - Rcpp::traits::input_parameter&>::type ssl_ca( - ssl_caSEXP); - Rcpp::traits::input_parameter&>::type ssl_capath( - ssl_capathSEXP); - Rcpp::traits::input_parameter&>::type ssl_cipher( - ssl_cipherSEXP); - Rcpp::traits::input_parameter::type timeout(timeoutSEXP); - Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); - rcpp_result_gen = Rcpp::wrap( - connection_create(host, user, password, db, port, unix_socket, - client_flag, groups, default_file, ssl_key, ssl_cert, - ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter&>::type host( + hostSEXP); + Rcpp::traits::input_parameter&>::type user( + userSEXP); + Rcpp::traits::input_parameter&>::type password( + passwordSEXP); + Rcpp::traits::input_parameter&>::type db( + dbSEXP); + Rcpp::traits::input_parameter::type port(portSEXP); + Rcpp::traits::input_parameter&>::type + unix_socket(unix_socketSEXP); + Rcpp::traits::input_parameter::type client_flag( + client_flagSEXP); + Rcpp::traits::input_parameter&>::type groups( + groupsSEXP); + Rcpp::traits::input_parameter&>::type + default_file(default_fileSEXP); + Rcpp::traits::input_parameter&>::type ssl_key( + ssl_keySEXP); + Rcpp::traits::input_parameter&>::type ssl_cert( + ssl_certSEXP); + Rcpp::traits::input_parameter&>::type ssl_ca( + ssl_caSEXP); + Rcpp::traits::input_parameter&>::type + ssl_capath(ssl_capathSEXP); + Rcpp::traits::input_parameter&>::type + ssl_cipher(ssl_cipherSEXP); + Rcpp::traits::input_parameter::type timeout(timeoutSEXP); + Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); + rcpp_result_gen = Rcpp::wrap( + connection_create(host, user, password, db, port, unix_socket, + client_flag, groups, default_file, ssl_key, ssl_cert, + ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); + return rcpp_result_gen; + END_RCPP } // connection_valid bool connection_valid(XPtr con_); RcppExport SEXP _RMariaDB_connection_valid(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); + return rcpp_result_gen; + END_RCPP } // connection_release void connection_release(XPtr con_); RcppExport SEXP _RMariaDB_connection_release(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - connection_release(con_); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + connection_release(con_); + return R_NilValue; + END_RCPP } // connection_info List connection_info(DbConnection* con); RcppExport SEXP _RMariaDB_connection_info(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_info(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_info(con)); + return rcpp_result_gen; + END_RCPP } // connection_quote_string CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs); RcppExport SEXP _RMariaDB_connection_quote_string(SEXP conSEXP, SEXP xsSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - Rcpp::traits::input_parameter::type xs(xsSEXP); - rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + Rcpp::traits::input_parameter::type xs(xsSEXP); + rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); + return rcpp_result_gen; + END_RCPP } // connection_begin_transaction void connection_begin_transaction(XPtr con); RcppExport SEXP _RMariaDB_connection_begin_transaction(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_begin_transaction(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_begin_transaction(con); + return R_NilValue; + END_RCPP } // connection_commit void connection_commit(XPtr con); RcppExport SEXP _RMariaDB_connection_commit(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_commit(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_commit(con); + return R_NilValue; + END_RCPP } // connection_rollback void connection_rollback(XPtr con); RcppExport SEXP _RMariaDB_connection_rollback(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_rollback(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_rollback(con); + return R_NilValue; + END_RCPP } // connection_is_transacting bool connection_is_transacting(DbConnection* con); RcppExport SEXP _RMariaDB_connection_is_transacting(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); + return rcpp_result_gen; + END_RCPP } // driver_init void driver_init(); RcppExport SEXP _RMariaDB_driver_init() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_init(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_init(); + return R_NilValue; + END_RCPP } // driver_done void driver_done(); RcppExport SEXP _RMariaDB_driver_done() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_done(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_done(); + return R_NilValue; + END_RCPP } // version IntegerVector version(); RcppExport SEXP _RMariaDB_version() { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - rcpp_result_gen = Rcpp::wrap(version()); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = Rcpp::wrap(version()); + return rcpp_result_gen; + END_RCPP } // init_logging void init_logging(const std::string& log_level); RcppExport SEXP _RMariaDB_init_logging(SEXP log_levelSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type log_level( - log_levelSEXP); - init_logging(log_level); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type log_level( + log_levelSEXP); + init_logging(log_level); + return R_NilValue; + END_RCPP } // result_create XPtr result_create(XPtr con, std::string sql, bool is_statement); RcppExport SEXP _RMariaDB_result_create(SEXP conSEXP, SEXP sqlSEXP, SEXP is_statementSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - Rcpp::traits::input_parameter::type sql(sqlSEXP); - Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); - rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + Rcpp::traits::input_parameter::type sql(sqlSEXP); + Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); + rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); + return rcpp_result_gen; + END_RCPP } // result_release void result_release(XPtr res); RcppExport SEXP _RMariaDB_result_release(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res(resSEXP); - result_release(res); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res(resSEXP); + result_release(res); + return R_NilValue; + END_RCPP } // result_valid bool result_valid(XPtr res_); RcppExport SEXP _RMariaDB_result_valid(SEXP res_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res_(res_SEXP); - rcpp_result_gen = Rcpp::wrap(result_valid(res_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res_(res_SEXP); + rcpp_result_gen = Rcpp::wrap(result_valid(res_)); + return rcpp_result_gen; + END_RCPP } // result_fetch List result_fetch(DbResult* res, const int n); RcppExport SEXP _RMariaDB_result_fetch(SEXP resSEXP, SEXP nSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type n(nSEXP); - rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type n(nSEXP); + rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); + return rcpp_result_gen; + END_RCPP } // result_bind void result_bind(DbResult* res, List params); RcppExport SEXP _RMariaDB_result_bind(SEXP resSEXP, SEXP paramsSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type params(paramsSEXP); - result_bind(res, params); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type params(paramsSEXP); + result_bind(res, params); + return R_NilValue; + END_RCPP } // result_has_completed bool result_has_completed(DbResult* res); RcppExport SEXP _RMariaDB_result_has_completed(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_fetched int result_rows_fetched(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_fetched(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_affected int result_rows_affected(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_affected(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); + return rcpp_result_gen; + END_RCPP } // result_column_info List result_column_info(DbResult* res); RcppExport SEXP _RMariaDB_result_column_info(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_column_info(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_column_info(res)); + return rcpp_result_gen; + END_RCPP } static const R_CallMethodDef CallEntries[] = { @@ -328,6 +329,6 @@ static const R_CallMethodDef CallEntries[] = { {NULL, NULL, 0}}; RcppExport void R_init_RMariaDB(DllInfo* dll) { - R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); - R_useDynamicSymbols(dll, FALSE); + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); } diff --git a/src/connection.cpp b/src/connection.cpp index 14e4fcbf..7a8d17af 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -12,81 +12,81 @@ XPtr connection_create( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; + LOG_VERBOSE; - DbConnection* pConnPtr = new DbConnection; - try { - pConnPtr->connect(host, user, password, db, port, unix_socket, client_flag, - groups, default_file, ssl_key, ssl_cert, ssl_ca, - ssl_capath, ssl_cipher, timeout, reconnect); - } catch (...) { - delete pConnPtr; - throw; - } + DbConnection* pConnPtr = new DbConnection; + try { + pConnPtr->connect(host, user, password, db, port, unix_socket, + client_flag, groups, default_file, ssl_key, ssl_cert, + ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect); + } catch (...) { + delete pConnPtr; + throw; + } - DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); + DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); - return XPtr(pConn, true); + return XPtr(pConn, true); } // [[Rcpp::export]] bool connection_valid(XPtr con_) { - DbConnectionPtr* con = con_.get(); - return con && con->get()->is_valid(); + DbConnectionPtr* con = con_.get(); + return con && con->get()->is_valid(); } // [[Rcpp::export]] void connection_release(XPtr con_) { - if (!connection_valid(con_)) { - warning("Already disconnected"); - return; - } - - DbConnectionPtr* con = con_.get(); - con->get()->disconnect(); - con_.release(); + if (!connection_valid(con_)) { + warning("Already disconnected"); + return; + } + + DbConnectionPtr* con = con_.get(); + con->get()->disconnect(); + con_.release(); } // [[Rcpp::export]] List connection_info(DbConnection* con) { - return con->info(); + return con->info(); } // Quoting // [[Rcpp::export]] CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs) { - R_xlen_t n = xs.size(); - CharacterVector output(n); + R_xlen_t n = xs.size(); + CharacterVector output(n); - for (R_xlen_t i = 0; i < n; ++i) { - String x = xs[i]; - output[i] = con->quote_string(x); - } + for (R_xlen_t i = 0; i < n; ++i) { + String x = xs[i]; + output[i] = con->quote_string(x); + } - return output; + return output; } // Transactions // [[Rcpp::export]] void connection_begin_transaction(XPtr con) { - (*con)->begin_transaction(); + (*con)->begin_transaction(); } // [[Rcpp::export]] void connection_commit(XPtr con) { - (*con)->commit(); + (*con)->commit(); } // [[Rcpp::export]] void connection_rollback(XPtr con) { - (*con)->rollback(); + (*con)->rollback(); } // [[Rcpp::export]] bool connection_is_transacting(DbConnection* con) { - return con->is_transacting(); + return con->is_transacting(); } // Specific functions @@ -97,10 +97,10 @@ namespace Rcpp { template <> DbConnection* as(SEXP x) { - DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); - if (!connection) - stop("Invalid connection"); - return connection->get(); + DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); + if (!connection) + stop("Invalid connection"); + return connection->get(); } } // namespace Rcpp diff --git a/src/driver.cpp b/src/driver.cpp index aa940f86..5c05fbbe 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -10,22 +10,22 @@ // [[Rcpp::export]] void driver_init() { - mysql_library_init(0, NULL, NULL); + mysql_library_init(0, NULL, NULL); } // [[Rcpp::export]] void driver_done() { - mysql_library_end(); + mysql_library_end(); } // [[Rcpp::export]] IntegerVector version() { - return IntegerVector::create( - _[SERVER_VERSION] = MYSQL_VERSION_ID, - _[mysql_get_client_info()] = mysql_get_client_version()); + return IntegerVector::create( + _[SERVER_VERSION] = MYSQL_VERSION_ID, + _[mysql_get_client_info()] = mysql_get_client_version()); } // [[Rcpp::export]] void init_logging(const std::string& log_level) { - plog::init_r(log_level); + plog::init_r(log_level); } diff --git a/src/integer64.h b/src/integer64.h index 2f3b934c..2b0a6f42 100644 --- a/src/integer64.h +++ b/src/integer64.h @@ -6,7 +6,7 @@ #define NA_INTEGER64 (static_cast(0x8000000000000000)) inline int64_t* INTEGER64(SEXP x) { - return reinterpret_cast(REAL(x)); + return reinterpret_cast(REAL(x)); } #endif // RMARIADB_INTEGER64_H diff --git a/src/result.cpp b/src/result.cpp index 6a11326b..38a448fa 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -5,60 +5,60 @@ // [[Rcpp::export]] XPtr result_create(XPtr con, std::string sql, bool is_statement = false) { - (*con)->check_connection(); - DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); - return XPtr(res, true); + (*con)->check_connection(); + DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); + return XPtr(res, true); } // [[Rcpp::export]] void result_release(XPtr res) { - res.release(); + res.release(); } // [[Rcpp::export]] bool result_valid(XPtr res_) { - DbResult* res = res_.get(); - return res != NULL && res->is_active(); + DbResult* res = res_.get(); + return res != NULL && res->is_active(); } // [[Rcpp::export]] List result_fetch(DbResult* res, const int n) { - return res->fetch(n); + return res->fetch(n); } // [[Rcpp::export]] void result_bind(DbResult* res, List params) { - res->bind(params); + res->bind(params); } // [[Rcpp::export]] bool result_has_completed(DbResult* res) { - return res->complete(); + return res->complete(); } // [[Rcpp::export]] int result_rows_fetched(DbResult* res) { - return res->n_rows_fetched(); + return res->n_rows_fetched(); } // [[Rcpp::export]] int result_rows_affected(DbResult* res) { - return res->n_rows_affected(); + return res->n_rows_affected(); } // [[Rcpp::export]] List result_column_info(DbResult* res) { - return res->get_column_info(); + return res->get_column_info(); } namespace Rcpp { template <> DbResult* as(SEXP x) { - DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); - if (!result) - stop("Invalid result set"); - return result; + DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); + if (!result) + stop("Invalid result set"); + return result; } } // namespace Rcpp From 01866a72b8ff7c1b1d04c354bda2c42e881493b9 Mon Sep 17 00:00:00 2001 From: Antonov Misha Date: Tue, 15 Nov 2022 12:00:35 +0000 Subject: [PATCH 6/9] remove case indent --- .clang-format | 3 +- src/DbConnection.cpp | 269 ++++++++++++------------ src/DbConnection.h | 90 ++++---- src/DbResult.cpp | 69 +++---- src/DbResult.h | 36 ++-- src/MariaBinding.cpp | 424 +++++++++++++++++++------------------- src/MariaBinding.h | 42 ++-- src/MariaResult.cpp | 26 +-- src/MariaResult.h | 18 +- src/MariaResultImpl.h | 24 +-- src/MariaResultPrep.cpp | 323 +++++++++++++++-------------- src/MariaResultPrep.h | 66 +++--- src/MariaResultSimple.cpp | 46 ++--- src/MariaResultSimple.h | 30 +-- src/MariaRow.cpp | 380 +++++++++++++++++----------------- src/MariaRow.h | 69 +++---- src/MariaTypes.cpp | 260 +++++++++++------------ src/MariaTypes.h | 18 +- src/RcppExports.cpp | 361 ++++++++++++++++---------------- src/connection.cpp | 76 +++---- src/driver.cpp | 12 +- src/integer64.h | 2 +- src/result.cpp | 32 +-- 23 files changed, 1336 insertions(+), 1340 deletions(-) diff --git a/.clang-format b/.clang-format index d2139802..037de4f9 100644 --- a/.clang-format +++ b/.clang-format @@ -1,8 +1,9 @@ BasedOnStyle: Google Language: Cpp TabWidth: 4 -IndentWidth: 4 +IndentWidth: 2 UseTab: ForIndentation +IndentCaseLabels: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never AccessModifierOffset: -4 \ No newline at end of file diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index d02ffe58..d1447e85 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -5,16 +5,16 @@ DbConnection::DbConnection() : pConn_(NULL), pCurrentResult_(NULL), transacting_(false) { - LOG_VERBOSE; + LOG_VERBOSE; } DbConnection::~DbConnection() { - LOG_VERBOSE; + LOG_VERBOSE; - if (is_valid()) { - warning("call dbDisconnect() when finished working with a connection"); - disconnect(); - } + if (is_valid()) { + warning("call dbDisconnect() when finished working with a connection"); + disconnect(); + } } void DbConnection::connect( @@ -27,201 +27,200 @@ void DbConnection::connect( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; - - this->pConn_ = mysql_init(NULL); - // Enable LOCAL INFILE for fast data ingest - unsigned int local_infile = 1; - mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); - // Default to UTF-8 - mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); - if (!groups.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, - as(groups).c_str()); - if (!default_file.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, - as(default_file).c_str()); - - if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || - !ssl_capath.isNull() || !ssl_cipher.isNull()) { - mysql_ssl_set( - this->pConn_, - ssl_key.isNull() ? NULL : as(ssl_key).c_str(), - ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), - ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), - ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), - ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); - } - if (timeout > 0) { - mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); - } - if (reconnect) { - my_bool reconnect_ = 1; - mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); - } - - LOG_VERBOSE; - - if (!mysql_real_connect( - this->pConn_, host.isNull() ? NULL : as(host).c_str(), - user.isNull() ? NULL : as(user).c_str(), - password.isNull() ? NULL : as(password).c_str(), - db.isNull() ? NULL : as(db).c_str(), port, - unix_socket.isNull() ? NULL : as(unix_socket).c_str(), - client_flag)) { - std::string error = mysql_error(this->pConn_); - mysql_close(this->pConn_); - this->pConn_ = NULL; - - stop("Failed to connect: %s", error.c_str()); - } + LOG_VERBOSE; + + this->pConn_ = mysql_init(NULL); + // Enable LOCAL INFILE for fast data ingest + unsigned int local_infile = 1; + mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); + // Default to UTF-8 + mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); + if (!groups.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, + as(groups).c_str()); + if (!default_file.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, + as(default_file).c_str()); + + if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || + !ssl_capath.isNull() || !ssl_cipher.isNull()) { + mysql_ssl_set( + this->pConn_, + ssl_key.isNull() ? NULL : as(ssl_key).c_str(), + ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), + ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), + ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), + ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); + } + if (timeout > 0) { + mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); + } + if (reconnect) { + my_bool reconnect_ = 1; + mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); + } + + LOG_VERBOSE; + + if (!mysql_real_connect( + this->pConn_, host.isNull() ? NULL : as(host).c_str(), + user.isNull() ? NULL : as(user).c_str(), + password.isNull() ? NULL : as(password).c_str(), + db.isNull() ? NULL : as(db).c_str(), port, + unix_socket.isNull() ? NULL : as(unix_socket).c_str(), + client_flag)) { + std::string error = mysql_error(this->pConn_); + mysql_close(this->pConn_); + this->pConn_ = NULL; + + stop("Failed to connect: %s", error.c_str()); + } } void DbConnection::disconnect() { - if (!is_valid()) - return; + if (!is_valid()) + return; - if (has_query()) { - warning( - "%s\n%s", "There is a result object still in use.", - "The connection will be automatically released when it is closed"); - } + if (has_query()) { + warning("%s\n%s", "There is a result object still in use.", + "The connection will be automatically released when it is closed"); + } - try { - mysql_close(get_conn()); - } catch (...) { - }; + try { + mysql_close(get_conn()); + } catch (...) { + }; - pConn_ = NULL; + pConn_ = NULL; } bool DbConnection::is_valid() { - return !!get_conn(); + return !!get_conn(); } void DbConnection::check_connection() { - if (!is_valid()) { - stop("Invalid or closed connection"); - } + if (!is_valid()) { + stop("Invalid or closed connection"); + } } List DbConnection::info() { - return List::create( - _["host"] = std::string(pConn_->host), - _["username"] = std::string(pConn_->user), - _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), - _["con.type"] = std::string(mysql_get_host_info(pConn_)), - _["db.version"] = std::string(mysql_get_server_info(pConn_)), - _["port"] = NA_INTEGER, - _["protocol.version"] = (int)mysql_get_proto_info(pConn_), - _["thread.id"] = (int)mysql_thread_id(pConn_)); + return List::create( + _["host"] = std::string(pConn_->host), + _["username"] = std::string(pConn_->user), + _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), + _["con.type"] = std::string(mysql_get_host_info(pConn_)), + _["db.version"] = std::string(mysql_get_server_info(pConn_)), + _["port"] = NA_INTEGER, + _["protocol.version"] = (int)mysql_get_proto_info(pConn_), + _["thread.id"] = (int)mysql_thread_id(pConn_)); } MYSQL* DbConnection::get_conn() { - return pConn_; + return pConn_; } SEXP DbConnection::quote_string(const String& input) { - if (input == NA_STRING) - return get_null_string(); + if (input == NA_STRING) + return get_null_string(); - const char* input_cstr = input.get_cstring(); - size_t input_len = strlen(input_cstr); + const char* input_cstr = input.get_cstring(); + size_t input_len = strlen(input_cstr); - // Create buffer with enough room to escape every character - std::string output = "'"; - output.resize(input_len * 2 + 3); + // Create buffer with enough room to escape every character + std::string output = "'"; + output.resize(input_len * 2 + 3); - size_t end = - mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); + size_t end = + mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); - output.resize(end + 1); - output.append("'"); - return Rf_mkCharCE(output.c_str(), CE_UTF8); + output.resize(end + 1); + output.append("'"); + return Rf_mkCharCE(output.c_str(), CE_UTF8); } SEXP DbConnection::get_null_string() { - static RObject null = Rf_mkCharCE("NULL", CE_UTF8); - return null; + static RObject null = Rf_mkCharCE("NULL", CE_UTF8); + return null; } void DbConnection::set_current_result(DbResult* pResult) { - if (pResult == pCurrentResult_) - return; + if (pResult == pCurrentResult_) + return; - if (pCurrentResult_ != NULL) { - if (pResult != NULL) - warning("Cancelling previous query"); + if (pCurrentResult_ != NULL) { + if (pResult != NULL) + warning("Cancelling previous query"); - pCurrentResult_->close(); - } - pCurrentResult_ = pResult; + pCurrentResult_->close(); + } + pCurrentResult_ = pResult; } void DbConnection::reset_current_result(DbResult* pResult) { - // FIXME: What to do if not current result is reset? - if (pResult != pCurrentResult_) - return; + // FIXME: What to do if not current result is reset? + if (pResult != pCurrentResult_) + return; - pCurrentResult_->close(); - pCurrentResult_ = NULL; + pCurrentResult_->close(); + pCurrentResult_ = NULL; } bool DbConnection::is_current_result(const DbResult* pResult) const { - return pCurrentResult_ == pResult; + return pCurrentResult_ == pResult; } bool DbConnection::has_query() { - return pCurrentResult_ != NULL; + return pCurrentResult_ != NULL; } bool DbConnection::exec(const std::string& sql) { - check_connection(); + check_connection(); - if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) - stop("Error executing query: %s", mysql_error(pConn_)); + if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) + stop("Error executing query: %s", mysql_error(pConn_)); - MYSQL_RES* res = mysql_store_result(pConn_); - if (res != NULL) - mysql_free_result(res); + MYSQL_RES* res = mysql_store_result(pConn_); + if (res != NULL) + mysql_free_result(res); - autocommit(); + autocommit(); - return true; + return true; } void DbConnection::begin_transaction() { - if (is_transacting()) - stop("Nested transactions not supported."); - check_connection(); + if (is_transacting()) + stop("Nested transactions not supported."); + check_connection(); - transacting_ = true; + transacting_ = true; } void DbConnection::commit() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_commit(get_conn()); - transacting_ = false; + mysql_commit(get_conn()); + transacting_ = false; } void DbConnection::rollback() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_rollback(get_conn()); - transacting_ = false; + mysql_rollback(get_conn()); + transacting_ = false; } bool DbConnection::is_transacting() const { - return transacting_; + return transacting_; } void DbConnection::autocommit() { - if (!is_transacting() && get_conn()) { - mysql_commit(get_conn()); - } + if (!is_transacting() && get_conn()) { + mysql_commit(get_conn()); + } } diff --git a/src/DbConnection.h b/src/DbConnection.h index e9179e94..c166a857 100644 --- a/src/DbConnection.h +++ b/src/DbConnection.h @@ -11,51 +11,51 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class DbConnection : boost::noncopyable { - MYSQL* pConn_; - DbResult* pCurrentResult_; - bool transacting_; - -public: - DbConnection(); - ~DbConnection(); - -public: - void connect(const Nullable& host, - const Nullable& user, - const Nullable& password, - const Nullable& db, unsigned int port, - const Nullable& unix_socket, - unsigned long client_flag, const Nullable& groups, - const Nullable& default_file, - const Nullable& ssl_key, - const Nullable& ssl_cert, - const Nullable& ssl_ca, - const Nullable& ssl_capath, - const Nullable& ssl_cipher, int timeout, - bool reconnect); - void disconnect(); - bool is_valid(); - void check_connection(); - - List info(); - MYSQL* get_conn(); - - SEXP quote_string(const String& input); - static SEXP get_null_string(); - - // Cancels previous query, if needed. - void set_current_result(DbResult* pResult); - void reset_current_result(DbResult* pResult); - bool is_current_result(const DbResult* pResult) const; - bool has_query(); - - bool exec(const std::string& sql); - - void begin_transaction(); - void commit(); - void rollback(); - bool is_transacting() const; - void autocommit(); + MYSQL* pConn_; + DbResult* pCurrentResult_; + bool transacting_; + + public: + DbConnection(); + ~DbConnection(); + + public: + void connect(const Nullable& host, + const Nullable& user, + const Nullable& password, + const Nullable& db, unsigned int port, + const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, + const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, + bool reconnect); + void disconnect(); + bool is_valid(); + void check_connection(); + + List info(); + MYSQL* get_conn(); + + SEXP quote_string(const String& input); + static SEXP get_null_string(); + + // Cancels previous query, if needed. + void set_current_result(DbResult* pResult); + void reset_current_result(DbResult* pResult); + bool is_current_result(const DbResult* pResult) const; + bool has_query(); + + bool exec(const std::string& sql); + + void begin_transaction(); + void commit(); + void rollback(); + bool is_transacting() const; + void autocommit(); }; #endif diff --git a/src/DbResult.cpp b/src/DbResult.cpp index 440c111a..af53a890 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -7,79 +7,78 @@ // Construction //////////////////////////////////////////////////////////////// DbResult::DbResult(const DbConnectionPtr& pConn) : pConn_(pConn) { - pConn_->check_connection(); + pConn_->check_connection(); - // subclass constructor can throw, the destructor will remove the - // current result set - pConn_->set_current_result(this); + // subclass constructor can throw, the destructor will remove the + // current result set + pConn_->set_current_result(this); } DbResult::~DbResult() { - try { - if (is_active()) { - pConn_->reset_current_result(this); - } - } catch (...) { + try { + if (is_active()) { + pConn_->reset_current_result(this); } + } catch (...) { + } } // Publics ///////////////////////////////////////////////////////////////////// bool DbResult::complete() const { - return (impl == NULL) || impl->complete(); + return (impl == NULL) || impl->complete(); } bool DbResult::is_active() const { - return pConn_->is_current_result(this); + return pConn_->is_current_result(this); } int DbResult::n_rows_fetched() { - return impl->n_rows_fetched(); + return impl->n_rows_fetched(); } int DbResult::n_rows_affected() { - return impl->n_rows_affected(); + return impl->n_rows_affected(); } void DbResult::bind(const List& params) { - validate_params(params); - impl->bind(params); + validate_params(params); + impl->bind(params); } List DbResult::fetch(const int n_max) { - if (!is_active()) - stop("Inactive result set"); + if (!is_active()) + stop("Inactive result set"); - return impl->fetch(n_max); + return impl->fetch(n_max); } List DbResult::get_column_info() { - List out = impl->get_column_info(); + List out = impl->get_column_info(); - out.attr("row.names") = - IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); - out.attr("class") = "data.frame"; + out.attr("row.names") = IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); + out.attr("class") = "data.frame"; - return out; + return out; } void DbResult::close() { - // Called from destructor - if (impl) - impl->close(); + // Called from destructor + if (impl) + impl->close(); } // Privates /////////////////////////////////////////////////////////////////// void DbResult::validate_params(const List& params) const { - if (params.size() != 0) { - SEXP first_col = params[0]; - int n = Rf_length(first_col); - - for (int j = 1; j < params.size(); ++j) { - SEXP col = params[j]; - if (Rf_length(col) != n) - stop("Parameter %i does not have length %d.", j + 1, n); - } + if (params.size() != 0) { + SEXP first_col = params[0]; + int n = Rf_length(first_col); + + for (int j = 1; j < params.size(); ++j) { + SEXP col = params[j]; + if (Rf_length(col) != n) + stop("Parameter %i does not have length %d.", j + 1, n); } + } } diff --git a/src/DbResult.h b/src/DbResult.h index 96fb8ecb..625e54e7 100644 --- a/src/DbResult.h +++ b/src/DbResult.h @@ -13,32 +13,32 @@ typedef boost::shared_ptr DbConnectionPtr; // DbResult -------------------------------------------------------------------- class DbResult : boost::noncopyable { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; -protected: - boost::scoped_ptr impl; + protected: + boost::scoped_ptr impl; -protected: - DbResult(const DbConnectionPtr& pConn); + protected: + DbResult(const DbConnectionPtr& pConn); -public: - ~DbResult(); + public: + ~DbResult(); -public: - void close(); + public: + void close(); - bool complete() const; - bool is_active() const; - int n_rows_fetched(); - int n_rows_affected(); + bool complete() const; + bool is_active() const; + int n_rows_fetched(); + int n_rows_affected(); - void bind(const List& params); - List fetch(int n_max = -1); + void bind(const List& params); + List fetch(int n_max = -1); - List get_column_info(); + List get_column_info(); -private: - void validate_params(const List& params) const; + private: + void validate_params(const List& params) const; }; #endif // __RDBI_DB_RESULT__ diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index e598429f..59f52d87 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -12,253 +12,253 @@ MariaBinding::~MariaBinding() { } void MariaBinding::setup(MYSQL_STMT* statement_) { - LOG_VERBOSE; + LOG_VERBOSE; - statement = statement_; - p = static_cast(mysql_stmt_param_count(statement)); + statement = statement_; + p = static_cast(mysql_stmt_param_count(statement)); - bindings.resize(p); - types.resize(p); - is_null.resize(p); - time_buffers.resize(p); + bindings.resize(p); + types.resize(p); + is_null.resize(p); + time_buffers.resize(p); } void MariaBinding::init_binding(const List& params_) { - LOG_VERBOSE; + LOG_VERBOSE; - params = params_; + params = params_; - if (params.size() == 0) { - stop("Query has no parameters"); - } + if (params.size() == 0) { + stop("Query has no parameters"); + } - if (p != params.size()) { - stop("Number of params don't match (%i vs %i)", p, params.size()); - } + if (p != params.size()) { + stop("Number of params don't match (%i vs %i)", p, params.size()); + } - i = 0; + i = 0; - for (int j = 0; j < p; ++j) { - RObject param(params[j]); - MariaFieldType type = variable_type_from_object(param); - types[j] = type; + for (int j = 0; j < p; ++j) { + RObject param(params[j]); + MariaFieldType type = variable_type_from_object(param); + types[j] = type; - LOG_VERBOSE << j << " -> " << type_name(type); + LOG_VERBOSE << j << " -> " << type_name(type); - if (j == 0) { - n_rows = Rf_xlength(param); - } + if (j == 0) { + n_rows = Rf_xlength(param); + } - switch (type) { - case MY_LGL: - binding_update(j, MYSQL_TYPE_TINY, 1); - break; - case MY_INT32: - binding_update(j, MYSQL_TYPE_LONG, 4); - break; - case MY_DBL: - binding_update(j, MYSQL_TYPE_DOUBLE, 8); - break; - case MY_DATE: - binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); - break; - case MY_TIME: - binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); - break; - case MY_STR: - binding_update(j, MYSQL_TYPE_STRING, 0); - break; - case MY_RAW: - binding_update(j, MYSQL_TYPE_BLOB, 0); - break; - case MY_INT64: - binding_update(j, MYSQL_TYPE_LONGLONG, 0); - break; - } + switch (type) { + case MY_LGL: + binding_update(j, MYSQL_TYPE_TINY, 1); + break; + case MY_INT32: + binding_update(j, MYSQL_TYPE_LONG, 4); + break; + case MY_DBL: + binding_update(j, MYSQL_TYPE_DOUBLE, 8); + break; + case MY_DATE: + binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); + break; + case MY_TIME: + binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); + break; + case MY_STR: + binding_update(j, MYSQL_TYPE_STRING, 0); + break; + case MY_RAW: + binding_update(j, MYSQL_TYPE_BLOB, 0); + break; + case MY_INT64: + binding_update(j, MYSQL_TYPE_LONGLONG, 0); + break; } + } } bool MariaBinding::bind_next_row() { - LOG_VERBOSE; - - if (i >= n_rows) - return false; - - for (int j = 0; j < p; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types[j]); - - bool missing = false; - RObject col(params[j]); - - switch (types[j]) { - case MY_LGL: - if (LOGICAL(col)[i] == NA_LOGICAL) { - missing = true; - break; - } - bindings[j].buffer = &LOGICAL(col)[i]; - break; - case MY_INT32: - if (INTEGER(col)[i] == NA_INTEGER) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER(col)[i]; - break; - case MY_DBL: - if (ISNA(REAL(col)[i])) { - missing = true; - break; - } - bindings[j].buffer = &REAL(col)[i]; - break; - case MY_STR: - if (STRING_ELT(col, i) == NA_STRING) { - missing = true; - break; - } else { - SEXP string = STRING_ELT(col, i); - bindings[j].buffer = const_cast(CHAR(string)); - bindings[j].buffer_length = Rf_length(string); - } - break; - case MY_RAW: { - SEXP raw = VECTOR_ELT(col, i); - if (Rf_isNull(raw)) { - missing = true; - } else { - bindings[j].buffer_length = Rf_length(raw); - bindings[j].buffer = RAW(raw); - } - break; - } - case MY_DATE: - case MY_DATE_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - } else { - double val = REAL(col)[i]; - LOG_VERBOSE << val; - if (types[j] == MY_DATE) { - set_date_buffer(j, static_cast(::floor(val))); - clear_time_buffer(j); - } else { - double days = ::floor(val / 86400.0); - set_date_buffer(j, static_cast(days)); - set_time_buffer(j, val - days * 86400.0); - } - LOG_VERBOSE; - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - break; - } else { - double val = REAL(col)[i]; - clear_date_buffer(j); - set_time_buffer(j, val); - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_INT64: - if (INTEGER64(col)[i] == NA_INTEGER64) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER64(col)[i]; - break; + LOG_VERBOSE; + + if (i >= n_rows) + return false; + + for (int j = 0; j < p; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types[j]); + + bool missing = false; + RObject col(params[j]); + + switch (types[j]) { + case MY_LGL: + if (LOGICAL(col)[i] == NA_LOGICAL) { + missing = true; + break; + } + bindings[j].buffer = &LOGICAL(col)[i]; + break; + case MY_INT32: + if (INTEGER(col)[i] == NA_INTEGER) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER(col)[i]; + break; + case MY_DBL: + if (ISNA(REAL(col)[i])) { + missing = true; + break; + } + bindings[j].buffer = &REAL(col)[i]; + break; + case MY_STR: + if (STRING_ELT(col, i) == NA_STRING) { + missing = true; + break; + } else { + SEXP string = STRING_ELT(col, i); + bindings[j].buffer = const_cast(CHAR(string)); + bindings[j].buffer_length = Rf_length(string); + } + break; + case MY_RAW: { + SEXP raw = VECTOR_ELT(col, i); + if (Rf_isNull(raw)) { + missing = true; + } else { + bindings[j].buffer_length = Rf_length(raw); + bindings[j].buffer = RAW(raw); + } + break; + } + case MY_DATE: + case MY_DATE_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + } else { + double val = REAL(col)[i]; + LOG_VERBOSE << val; + if (types[j] == MY_DATE) { + set_date_buffer(j, static_cast(::floor(val))); + clear_time_buffer(j); + } else { + double days = ::floor(val / 86400.0); + set_date_buffer(j, static_cast(days)); + set_time_buffer(j, val - days * 86400.0); } - is_null[j] = missing; + LOG_VERBOSE; + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + break; + } else { + double val = REAL(col)[i]; + clear_date_buffer(j); + set_time_buffer(j, val); + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_INT64: + if (INTEGER64(col)[i] == NA_INTEGER64) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER64(col)[i]; + break; } + is_null[j] = missing; + } - LOG_DEBUG << "Binding"; - mysql_stmt_bind_param(statement, &bindings[0]); + LOG_DEBUG << "Binding"; + mysql_stmt_bind_param(statement, &bindings[0]); - LOG_DEBUG << "Done binding row " << i; - i++; - return true; + LOG_DEBUG << "Done binding row " << i; + i++; + return true; } void MariaBinding::binding_update(int j, enum_field_types type, int size) { - LOG_VERBOSE << j << ", " << type << ", " << size; + LOG_VERBOSE << j << ", " << type << ", " << size; - bindings[j].buffer_length = size; - bindings[j].buffer_type = type; - bindings[j].is_null = &is_null[j]; + bindings[j].buffer_length = size; + bindings[j].buffer_type = type; + bindings[j].is_null = &is_null[j]; } void MariaBinding::clear_date_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].year = 0; - time_buffers[j].month = 0; - time_buffers[j].day = 0; + LOG_VERBOSE << j; + time_buffers[j].year = 0; + time_buffers[j].month = 0; + time_buffers[j].day = 0; } void MariaBinding::set_date_buffer(int j, const int date) { - LOG_VERBOSE << date; - - // https://howardhinnant.github.io/date_algorithms.html#civil_from_days - const int date_0 = date + 719468; - const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; - const unsigned doe = - static_cast(date_0 - era * 146097); // [0, 146096] - LOG_VERBOSE << doe; - const unsigned yoe = - (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] - LOG_VERBOSE << yoe; - const int y = static_cast(yoe) + era * 400; - const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] - const unsigned mp = (5 * doy + 2) / 153; // [0, 11] - const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] - const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] - const unsigned yr = y + (m <= 2); - - // gmtime() fails for dates < 1970 on Windows - LOG_VERBOSE << date_0; - LOG_VERBOSE << yr; - LOG_VERBOSE << m; - LOG_VERBOSE << d; - - time_buffers[j].year = yr; - time_buffers[j].month = m; - time_buffers[j].day = d; + LOG_VERBOSE << date; + + // https://howardhinnant.github.io/date_algorithms.html#civil_from_days + const int date_0 = date + 719468; + const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; + const unsigned doe = + static_cast(date_0 - era * 146097); // [0, 146096] + LOG_VERBOSE << doe; + const unsigned yoe = + (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] + LOG_VERBOSE << yoe; + const int y = static_cast(yoe) + era * 400; + const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] + const unsigned mp = (5 * doy + 2) / 153; // [0, 11] + const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] + const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] + const unsigned yr = y + (m <= 2); + + // gmtime() fails for dates < 1970 on Windows + LOG_VERBOSE << date_0; + LOG_VERBOSE << yr; + LOG_VERBOSE << m; + LOG_VERBOSE << d; + + time_buffers[j].year = yr; + time_buffers[j].month = m; + time_buffers[j].day = d; } void MariaBinding::clear_time_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].hour = 0; - time_buffers[j].minute = 0; - time_buffers[j].second = 0; - time_buffers[j].second_part = 0; - time_buffers[j].neg = 0; + LOG_VERBOSE << j; + time_buffers[j].hour = 0; + time_buffers[j].minute = 0; + time_buffers[j].second = 0; + time_buffers[j].second_part = 0; + time_buffers[j].neg = 0; } void MariaBinding::set_time_buffer(int j, double time) { - LOG_VERBOSE << time; - - bool neg = false; - if (time < 0) { - neg = true; - time = -time; - } - double whole_seconds = ::trunc(time); - double frac_seconds = time - whole_seconds; - double whole_minutes = ::trunc(time / 60.0); - double seconds = whole_seconds - whole_minutes * 60.0; - double hours = ::trunc(time / 3600.0); - double minutes = whole_minutes - hours * 60.0; - - time_buffers[j].hour = static_cast(hours); - time_buffers[j].minute = static_cast(minutes); - time_buffers[j].second = static_cast(seconds); - time_buffers[j].second_part = - static_cast(frac_seconds * 1000000.0); - time_buffers[j].neg = neg; + LOG_VERBOSE << time; + + bool neg = false; + if (time < 0) { + neg = true; + time = -time; + } + double whole_seconds = ::trunc(time); + double frac_seconds = time - whole_seconds; + double whole_minutes = ::trunc(time / 60.0); + double seconds = whole_seconds - whole_minutes * 60.0; + double hours = ::trunc(time / 3600.0); + double minutes = whole_minutes - hours * 60.0; + + time_buffers[j].hour = static_cast(hours); + time_buffers[j].minute = static_cast(minutes); + time_buffers[j].second = static_cast(seconds); + time_buffers[j].second_part = + static_cast(frac_seconds * 1000000.0); + time_buffers[j].neg = neg; } diff --git a/src/MariaBinding.h b/src/MariaBinding.h index e66bd096..b1322bc1 100644 --- a/src/MariaBinding.h +++ b/src/MariaBinding.h @@ -7,33 +7,33 @@ #include "MariaTypes.h" class MariaBinding : public boost::noncopyable { - MYSQL_STMT* statement; - List params; + MYSQL_STMT* statement; + List params; - int p; - R_xlen_t i, n_rows; - std::vector bindings; - boost::container::vector is_null; - std::vector types; - std::vector time_buffers; + int p; + R_xlen_t i, n_rows; + std::vector bindings; + boost::container::vector is_null; + std::vector types; + std::vector time_buffers; -public: - MariaBinding(); - ~MariaBinding(); + public: + MariaBinding(); + ~MariaBinding(); -public: - void setup(MYSQL_STMT* statement_); + public: + void setup(MYSQL_STMT* statement_); - void init_binding(const List& params); - bool bind_next_row(); + void init_binding(const List& params); + bool bind_next_row(); -private: - void binding_update(int j, enum_field_types type, int size); + private: + void binding_update(int j, enum_field_types type, int size); - void clear_date_buffer(int j); - void set_date_buffer(int j, int date); - void clear_time_buffer(int j); - void set_time_buffer(int j, double time); + void clear_date_buffer(int j); + void set_date_buffer(int j, int date); + void clear_time_buffer(int j); + void set_time_buffer(int j, double time); }; #endif diff --git a/src/MariaResult.cpp b/src/MariaResult.cpp index a25e20de..1708e0f8 100644 --- a/src/MariaResult.cpp +++ b/src/MariaResult.cpp @@ -9,25 +9,25 @@ MariaResult::MariaResult(const DbConnectionPtr& pConn, const std::string& sql, bool is_statement) : DbResult(pConn) { - boost::scoped_ptr res( - new MariaResultPrep(pConn, is_statement)); - try { - res->send_query(sql); - } catch (const MariaResultPrep::UnsupportedPS& e) { - res.reset(NULL); - // is_statement info might be worthwhile to pass to simple queries as - // well - res.reset(new MariaResultSimple(pConn, is_statement)); - res->send_query(sql); - } + boost::scoped_ptr res( + new MariaResultPrep(pConn, is_statement)); + try { + res->send_query(sql); + } catch (const MariaResultPrep::UnsupportedPS& e) { + res.reset(NULL); + // is_statement info might be worthwhile to pass to simple queries as + // well + res.reset(new MariaResultSimple(pConn, is_statement)); + res->send_query(sql); + } - res.swap(impl); + res.swap(impl); } DbResult* MariaResult::create_and_send_query(const DbConnectionPtr& con, const std::string& sql, bool is_statement) { - return new MariaResult(con, sql, is_statement); + return new MariaResult(con, sql, is_statement); } // Publics ///////////////////////////////////////////////////////////////////// diff --git a/src/MariaResult.h b/src/MariaResult.h index 6835fe38..1586aa66 100644 --- a/src/MariaResult.h +++ b/src/MariaResult.h @@ -6,17 +6,17 @@ // MariaResult ----------------------------------------------------------------- class MariaResult : public DbResult { -protected: - MariaResult(const DbConnectionPtr& pConn, const std::string& sql, - bool is_statement); + protected: + MariaResult(const DbConnectionPtr& pConn, const std::string& sql, + bool is_statement); -public: - static DbResult* create_and_send_query(const DbConnectionPtr& con, - const std::string& sql, - bool is_statement); + public: + static DbResult* create_and_send_query(const DbConnectionPtr& con, + const std::string& sql, + bool is_statement); -public: - void close(); + public: + void close(); }; #endif // __RMARIADB_MARIA_RESULT__ diff --git a/src/MariaResultImpl.h b/src/MariaResultImpl.h index 1bf2791c..7e592174 100644 --- a/src/MariaResultImpl.h +++ b/src/MariaResultImpl.h @@ -2,23 +2,23 @@ #define RMARIADB_MARIARESULTIMPL_H class MariaResultImpl { -public: - MariaResultImpl(); - virtual ~MariaResultImpl(); + public: + MariaResultImpl(); + virtual ~MariaResultImpl(); -public: - virtual void send_query(const std::string& sql) = 0; - virtual void close() = 0; + public: + virtual void send_query(const std::string& sql) = 0; + virtual void close() = 0; - virtual void bind(const List& params) = 0; + virtual void bind(const List& params) = 0; - virtual List get_column_info() = 0; + virtual List get_column_info() = 0; - virtual List fetch(int n_max = -1) = 0; + virtual List fetch(int n_max = -1) = 0; - virtual int n_rows_affected() = 0; - virtual int n_rows_fetched() = 0; - virtual bool complete() const = 0; + virtual int n_rows_affected() = 0; + virtual int n_rows_fetched() = 0; + virtual bool complete() const = 0; }; #endif // RMARIADB_MARIARESULTIMPL_H diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index 7299e08f..95938a54 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -18,249 +18,248 @@ MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, bound_(false), complete_(false), is_statement_(is_statement) { - pStatement_ = mysql_stmt_init(pConn_->get_conn()); - if (pStatement_ == NULL) - stop("Out of memory"); + pStatement_ = mysql_stmt_init(pConn_->get_conn()); + if (pStatement_ == NULL) + stop("Out of memory"); } MariaResultPrep::~MariaResultPrep() { - MariaResultPrep::close(); + MariaResultPrep::close(); } void MariaResultPrep::send_query(const std::string& sql) { - LOG_DEBUG << sql; + LOG_DEBUG << sql; - LOG_DEBUG << "mysql_stmt_prepare()"; - if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { - if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { - throw UnsupportedPS(); - } - - throw_error(); + LOG_DEBUG << "mysql_stmt_prepare()"; + if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { + if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { + throw UnsupportedPS(); } - nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); - LOG_DEBUG << nParams_; + throw_error(); + } - // Need to set pSpec_ before calling execute() - pSpec_ = mysql_stmt_result_metadata(pStatement_); + nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); + LOG_DEBUG << nParams_; - if (nParams_ == 0) { - // Not parameterised so we can execute immediately - execute(); - bound_ = true; - } + // Need to set pSpec_ before calling execute() + pSpec_ = mysql_stmt_result_metadata(pStatement_); - if (has_result()) { - // Query returns results, so cache column names and types - cache_metadata(); - bindingOutput_.setup(pStatement_, types_); - } + if (nParams_ == 0) { + // Not parameterised so we can execute immediately + execute(); + bound_ = true; + } + + if (has_result()) { + // Query returns results, so cache column names and types + cache_metadata(); + bindingOutput_.setup(pStatement_, types_); + } } void MariaResultPrep::close() { - if (has_result()) { - mysql_free_result(pSpec_); - pSpec_ = NULL; - } + if (has_result()) { + mysql_free_result(pSpec_); + pSpec_ = NULL; + } - if (pStatement_ != NULL) { - mysql_stmt_close(pStatement_); - pStatement_ = NULL; - } + if (pStatement_ != NULL) { + mysql_stmt_close(pStatement_); + pStatement_ = NULL; + } - pConn_->autocommit(); + pConn_->autocommit(); } void MariaResultPrep::execute() { - LOG_VERBOSE; + LOG_VERBOSE; - complete_ = false; + complete_ = false; - LOG_DEBUG << "mysql_stmt_execute()"; - if (mysql_stmt_execute(pStatement_) != 0) { - LOG_VERBOSE; - throw_error(); - } - LOG_VERBOSE << "has_result()"; - if (!has_result() && !is_statement_) { - LOG_VERBOSE; - // try again after mysql_stmt_execute, in case pSpec_ == NULL - pSpec_ = mysql_stmt_result_metadata(pStatement_); - } - if (!has_result()) { - LOG_VERBOSE; - rowsAffected_ += mysql_stmt_affected_rows(pStatement_); - } + LOG_DEBUG << "mysql_stmt_execute()"; + if (mysql_stmt_execute(pStatement_) != 0) { + LOG_VERBOSE; + throw_error(); + } + LOG_VERBOSE << "has_result()"; + if (!has_result() && !is_statement_) { + LOG_VERBOSE; + // try again after mysql_stmt_execute, in case pSpec_ == NULL + pSpec_ = mysql_stmt_result_metadata(pStatement_); + } + if (!has_result()) { + LOG_VERBOSE; + rowsAffected_ += mysql_stmt_affected_rows(pStatement_); + } } void MariaResultPrep::bind(const List& params) { - rowsAffected_ = 0; + rowsAffected_ = 0; - bindingInput_.setup(pStatement_); - bindingInput_.init_binding(params); + bindingInput_.setup(pStatement_); + bindingInput_.init_binding(params); - if (has_result()) { - complete_ = true; - } else { - while (bindingInput_.bind_next_row()) { - execute(); - } + if (has_result()) { + complete_ = true; + } else { + while (bindingInput_.bind_next_row()) { + execute(); } + } - bound_ = true; + bound_ = true; } List MariaResultPrep::get_column_info() { - CharacterVector names(nCols_), types(nCols_); - for (int i = 0; i < nCols_; i++) { - names[i] = names_[i]; - types[i] = type_name(types_[i]); - } + CharacterVector names(nCols_), types(nCols_); + for (int i = 0; i < nCols_; i++) { + names[i] = names_[i]; + types[i] = type_name(types_[i]); + } - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } bool MariaResultPrep::has_result() const { - return pSpec_ != NULL; + return pSpec_ != NULL; } bool MariaResultPrep::step() { + LOG_VERBOSE; + + while (!fetch_row()) { LOG_VERBOSE; - while (!fetch_row()) { - LOG_VERBOSE; + if (!bindingInput_.bind_next_row()) + return false; + execute(); + } - if (!bindingInput_.bind_next_row()) - return false; - execute(); - } + rowsFetched_++; - rowsFetched_++; - - LOG_VERBOSE << rowsFetched_; - return true; + LOG_VERBOSE << rowsFetched_; + return true; } bool MariaResultPrep::fetch_row() { - LOG_VERBOSE; + LOG_VERBOSE; - if (complete_) - return false; + if (complete_) + return false; - LOG_VERBOSE << "mysql_stmt_fetch()"; - int result = mysql_stmt_fetch(pStatement_); + LOG_VERBOSE << "mysql_stmt_fetch()"; + int result = mysql_stmt_fetch(pStatement_); - LOG_VERBOSE << result; + LOG_VERBOSE << result; - switch (result) { - // We expect truncation whenever there's a string or blob - case MYSQL_DATA_TRUNCATED: - case 0: - return true; - case 1: - throw_error(); - case MYSQL_NO_DATA: - complete_ = true; - return false; - } + switch (result) { + // We expect truncation whenever there's a string or blob + case MYSQL_DATA_TRUNCATED: + case 0: + return true; + case 1: + throw_error(); + case MYSQL_NO_DATA: + complete_ = true; return false; + } + return false; } List MariaResultPrep::fetch(int n_max) { - if (!bound_) - stop("Query needs to be bound before fetching"); - if (!has_result()) { - if (names_.size() == 0) { - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and " - "also " - "avoid dbFetch()"); - } - return df_create(types_, names_, 0); + if (!bound_) + stop("Query needs to be bound before fetching"); + if (!has_result()) { + if (names_.size() == 0) { + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and " + "also " + "avoid dbFetch()"); } + return df_create(types_, names_, 0); + } - int n = (n_max < 0) ? 100 : n_max; - List out = df_create(types_, names_, n); - if (n == 0) - return out; - - int i = 0; - - for (;;) { - if (i >= n && n_max > 0) - break; + int n = (n_max < 0) ? 100 : n_max; + List out = df_create(types_, names_, n); + if (n == 0) + return out; - if (!step()) - break; + int i = 0; - if (i >= n) { - n *= 2; - out = df_resize(out, n); - } + for (;;) { + if (i >= n && n_max > 0) + break; - for (int j = 0; j < nCols_; ++j) { - // Rcout << i << "," << j << "\n"; - bindingOutput_.set_list_value(out[j], i, j); - } + if (!step()) + break; - ++i; - if (i % 1024 == 0) - checkUserInterrupt(); + if (i >= n) { + n *= 2; + out = df_resize(out, n); } - // Trim back to what we actually used - if (i < n) { - out = df_resize(out, i); + for (int j = 0; j < nCols_; ++j) { + // Rcout << i << "," << j << "\n"; + bindingOutput_.set_list_value(out[j], i, j); } - // Set up S3 classes - df_s3(out, types_); - return out; + ++i; + if (i % 1024 == 0) + checkUserInterrupt(); + } + + // Trim back to what we actually used + if (i < n) { + out = df_resize(out, i); + } + // Set up S3 classes + df_s3(out, types_); + + return out; } int MariaResultPrep::n_rows_affected() { - if (!bound_) - return NA_INTEGER; - // FIXME: > 2^32 rows? - return static_cast(rowsAffected_); + if (!bound_) + return NA_INTEGER; + // FIXME: > 2^32 rows? + return static_cast(rowsAffected_); } int MariaResultPrep::n_rows_fetched() { - if (!bound_) - return 0; - // FIXME: > 2^32 rows? - return static_cast(rowsFetched_); + if (!bound_) + return 0; + // FIXME: > 2^32 rows? + return static_cast(rowsFetched_); } bool MariaResultPrep::complete() const { - if (!bound_) - return FALSE; - return !has_result() || // query doesn't have results - complete_; // we've fetched all available results + if (!bound_) + return FALSE; + return !has_result() || // query doesn't have results + complete_; // we've fetched all available results } void MariaResultPrep::throw_error() { - stop("%s [%i]", mysql_stmt_error(pStatement_), - mysql_stmt_errno(pStatement_)); + stop("%s [%i]", mysql_stmt_error(pStatement_), mysql_stmt_errno(pStatement_)); } void MariaResultPrep::cache_metadata() { - LOG_VERBOSE; + LOG_VERBOSE; - nCols_ = mysql_num_fields(pSpec_); - MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); + nCols_ = mysql_num_fields(pSpec_); + MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); - for (int i = 0; i < nCols_; ++i) { - names_.push_back(fields[i].name); + for (int i = 0; i < nCols_; ++i) { + names_.push_back(fields[i].name); - bool binary = fields[i].charsetnr == 63; - bool length1 = fields[i].length == 1; - MariaFieldType type = - variable_type_from_field_type(fields[i].type, binary, length1); - types_.push_back(type); + bool binary = fields[i].charsetnr == 63; + bool length1 = fields[i].length == 1; + MariaFieldType type = + variable_type_from_field_type(fields[i].type, binary, length1); + types_.push_back(type); - LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type - << ", " << binary << ") => " << type_name(type); - } + LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type + << ", " << binary << ") => " << type_name(type); + } } diff --git a/src/MariaResultPrep.h b/src/MariaResultPrep.h index f07ef302..c1fe8cb3 100644 --- a/src/MariaResultPrep.h +++ b/src/MariaResultPrep.h @@ -14,52 +14,52 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultPrep : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - MYSQL_STMT* pStatement_; - MYSQL_RES* pSpec_; - uint64_t rowsAffected_, rowsFetched_; + MYSQL_STMT* pStatement_; + MYSQL_RES* pSpec_; + uint64_t rowsAffected_, rowsFetched_; - int nCols_, nParams_; - bool bound_, complete_; - bool is_statement_; + int nCols_, nParams_; + bool bound_, complete_; + bool is_statement_; - std::vector types_; - std::vector names_; - MariaBinding bindingInput_; - MariaRow bindingOutput_; + std::vector types_; + std::vector names_; + MariaBinding bindingInput_; + MariaRow bindingOutput_; -public: - MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); - ~MariaResultPrep(); + public: + MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); + ~MariaResultPrep(); -public: - virtual void send_query(const std::string& sql); - virtual void close(); + public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; -public: - class UnsupportedPS : public std::exception {}; + public: + class UnsupportedPS : public std::exception {}; -private: - void execute(); + private: + void execute(); - bool has_result() const; - bool step(); - bool fetch_row(); - void NORET throw_error(); + bool has_result() const; + bool step(); + bool fetch_row(); + void NORET throw_error(); -private: - void cache_metadata(); + private: + void cache_metadata(); }; #endif diff --git a/src/MariaResultSimple.cpp b/src/MariaResultSimple.cpp index 1ffaebc0..77c98b83 100644 --- a/src/MariaResultSimple.cpp +++ b/src/MariaResultSimple.cpp @@ -6,60 +6,60 @@ MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement) : pConn_(pConn) { - (void)is_statement; + (void)is_statement; } MariaResultSimple::~MariaResultSimple() { - MariaResultSimple::close(); + MariaResultSimple::close(); } void MariaResultSimple::send_query(const std::string& sql) { - LOG_DEBUG << sql; + LOG_DEBUG << sql; - exec(sql); + exec(sql); } void MariaResultSimple::close() { - LOG_VERBOSE; + LOG_VERBOSE; } void MariaResultSimple::bind(const List& /*params*/) { - LOG_VERBOSE; + LOG_VERBOSE; - stop( - "This query is not supported by the prepared statement protocol, no " - "parameters can be bound."); + stop( + "This query is not supported by the prepared statement protocol, no " + "parameters can be bound."); } List MariaResultSimple::get_column_info() { - CharacterVector names(0), types(0); + CharacterVector names(0), types(0); - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } List MariaResultSimple::fetch(int /*n_max*/) { - LOG_VERBOSE; - - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and also " - "avoid " - "dbFetch()"); - return df_create(std::vector(), std::vector(), - 0); + LOG_VERBOSE; + + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and also " + "avoid " + "dbFetch()"); + return df_create(std::vector(), std::vector(), + 0); } int MariaResultSimple::n_rows_affected() { - return 0; + return 0; } int MariaResultSimple::n_rows_fetched() { - return 0; + return 0; } bool MariaResultSimple::complete() const { - return true; + return true; } void MariaResultSimple::exec(const std::string& sql) { - pConn_->exec(sql); + pConn_->exec(sql); } diff --git a/src/MariaResultSimple.h b/src/MariaResultSimple.h index 9cf0f846..242cfe69 100644 --- a/src/MariaResultSimple.h +++ b/src/MariaResultSimple.h @@ -14,28 +14,28 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultSimple : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; -public: - MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); - ~MariaResultSimple(); + public: + MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); + ~MariaResultSimple(); -public: - virtual void send_query(const std::string& sql); - virtual void close(); + public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; -private: - void exec(const std::string& sql); + private: + void exec(const std::string& sql); }; #endif diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index d9730832..be0f3f03 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -13,245 +13,245 @@ MariaRow::~MariaRow() { void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& types) { - LOG_VERBOSE; - - pStatement_ = pStatement; - types_ = types; - n_ = static_cast(types_.size()); - - bindings_.resize(n_); - buffers_.resize(n_); - lengths_.resize(n_); - nulls_.resize(n_); - errors_.resize(n_); - - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types_[j]); - - // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html - switch (types_[j]) { - case MY_INT32: - bindings_[j].buffer_type = MYSQL_TYPE_LONG; - buffers_[j].resize(4); - break; - case MY_INT64: - bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; - buffers_[j].resize(8); - break; - case MY_DBL: - bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; - buffers_[j].resize(8); - break; - case MY_DATE: - bindings_[j].buffer_type = MYSQL_TYPE_DATE; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_TIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_STR: - bindings_[j].buffer_type = MYSQL_TYPE_STRING; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_RAW: - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_LGL: - // BIT(1) is bound to logical, in absence of dedicated type - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(4); - break; - } - - lengths_[j] = buffers_[j].size(); - bindings_[j].buffer_length = buffers_[j].size(); - if (bindings_[j].buffer_length > 0) - bindings_[j].buffer = &buffers_[j][0]; - else - bindings_[j].buffer = NULL; - bindings_[j].length = &lengths_[j]; - bindings_[j].is_null = &nulls_[j]; - bindings_[j].is_unsigned = true; - bindings_[j].error = &errors_[j]; - - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; - } + LOG_VERBOSE; - LOG_DEBUG << "mysql_stmt_bind_result()"; - if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { - stop("Error binding result: %s", mysql_stmt_error(pStatement)); - } + pStatement_ = pStatement; + types_ = types; + n_ = static_cast(types_.size()); + + bindings_.resize(n_); + buffers_.resize(n_); + lengths_.resize(n_); + nulls_.resize(n_); + errors_.resize(n_); + + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types_[j]); - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; + // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html + switch (types_[j]) { + case MY_INT32: + bindings_[j].buffer_type = MYSQL_TYPE_LONG; + buffers_[j].resize(4); + break; + case MY_INT64: + bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; + buffers_[j].resize(8); + break; + case MY_DBL: + bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; + buffers_[j].resize(8); + break; + case MY_DATE: + bindings_[j].buffer_type = MYSQL_TYPE_DATE; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_TIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_STR: + bindings_[j].buffer_type = MYSQL_TYPE_STRING; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_RAW: + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_LGL: + // BIT(1) is bound to logical, in absence of dedicated type + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(4); + break; } + + lengths_[j] = buffers_[j].size(); + bindings_[j].buffer_length = buffers_[j].size(); + if (bindings_[j].buffer_length > 0) + bindings_[j].buffer = &buffers_[j][0]; + else + bindings_[j].buffer = NULL; + bindings_[j].length = &lengths_[j]; + bindings_[j].is_null = &nulls_[j]; + bindings_[j].is_unsigned = true; + bindings_[j].error = &errors_[j]; + + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; + } + + LOG_DEBUG << "mysql_stmt_bind_result()"; + if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { + stop("Error binding result: %s", mysql_stmt_error(pStatement)); + } + + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; + } } bool MariaRow::is_null(int j) { - return nulls_[j] == 1; + return nulls_[j] == 1; } int MariaRow::value_bool(int j) { - if (is_null(j)) { - return NA_LOGICAL; - } else { - return static_cast(value_int(j) == 1); - } + if (is_null(j)) { + return NA_LOGICAL; + } else { + return static_cast(value_int(j) == 1); + } } int MariaRow::value_int(int j) { - return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); } int64_t MariaRow::value_int64(int j) { - return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); } double MariaRow::value_double(int j) { - return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); + return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); } SEXP MariaRow::value_string(int j) { - if (is_null(j)) - return NA_STRING; + if (is_null(j)) + return NA_STRING; - fetch_buffer(j); - int len = static_cast(buffers_[j].size()); - if (len == 0) - return R_BlankString; + fetch_buffer(j); + int len = static_cast(buffers_[j].size()); + if (len == 0) + return R_BlankString; - const char* val = reinterpret_cast(&buffers_[j][0]); - return Rf_mkCharLenCE(val, len, CE_UTF8); + const char* val = reinterpret_cast(&buffers_[j][0]); + return Rf_mkCharLenCE(val, len, CE_UTF8); } SEXP MariaRow::value_raw(int j) { - if (is_null(j)) - return R_NilValue; + if (is_null(j)) + return R_NilValue; - fetch_buffer(j); - SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); - memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); + fetch_buffer(j); + SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); + memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); - return bytes; + return bytes; } double MariaRow::value_date_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days) * 86400.0 + - static_cast(mytime->hour) * (60.0 * 60) + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; - LOG_VERBOSE << date_time; - return date_time; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days) * 86400.0 + + static_cast(mytime->hour) * (60.0 * 60) + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_date(int j) { - if (is_null(j)) - return NA_REAL; + if (is_null(j)) + return NA_REAL; - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days); - LOG_VERBOSE << date_time; - return date_time; + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days); + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - return static_cast(mytime->hour) * 3600.0 + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + return static_cast(mytime->hour) * 3600.0 + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; } void MariaRow::set_list_value(SEXP x, int i, int j) { - switch (types_[j]) { - case MY_INT32: - INTEGER(x)[i] = value_int(j); - break; - case MY_INT64: - INTEGER64(x)[i] = value_int64(j); - break; - case MY_DBL: - REAL(x)[i] = value_double(j); - break; - case MY_DATE: - REAL(x)[i] = value_date(j); - break; - case MY_DATE_TIME: - REAL(x)[i] = value_date_time(j); - break; - case MY_TIME: - REAL(x)[i] = value_time(j); - break; - case MY_STR: - SET_STRING_ELT(x, i, value_string(j)); - break; - case MY_RAW: - SET_VECTOR_ELT(x, i, value_raw(j)); - break; - case MY_LGL: - LOGICAL(x)[i] = value_bool(j); - break; - } + switch (types_[j]) { + case MY_INT32: + INTEGER(x)[i] = value_int(j); + break; + case MY_INT64: + INTEGER64(x)[i] = value_int64(j); + break; + case MY_DBL: + REAL(x)[i] = value_double(j); + break; + case MY_DATE: + REAL(x)[i] = value_date(j); + break; + case MY_DATE_TIME: + REAL(x)[i] = value_date_time(j); + break; + case MY_TIME: + REAL(x)[i] = value_time(j); + break; + case MY_STR: + SET_STRING_ELT(x, i, value_string(j)); + break; + case MY_RAW: + SET_VECTOR_ELT(x, i, value_raw(j)); + break; + case MY_LGL: + LOGICAL(x)[i] = value_bool(j); + break; + } } void MariaRow::fetch_buffer(int j) { - unsigned long length = lengths_[j]; - LOG_VERBOSE << length; + unsigned long length = lengths_[j]; + LOG_VERBOSE << length; - buffers_[j].resize(length); - if (length == 0) - return; + buffers_[j].resize(length); + if (length == 0) + return; - bindings_[j].buffer = &buffers_[j][0]; // might have moved - bindings_[j].buffer_length = length; + bindings_[j].buffer = &buffers_[j][0]; // might have moved + bindings_[j].buffer_length = length; - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; - LOG_DEBUG << "mysql_stmt_fetch_column()"; - int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); - LOG_VERBOSE << result; + LOG_DEBUG << "mysql_stmt_fetch_column()"; + int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); + LOG_VERBOSE << result; - if (result != 0) - stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); + if (result != 0) + stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); - // Reset buffer length to zero for next row - bindings_[j].buffer = NULL; - bindings_[j].buffer_length = 0; + // Reset buffer length to zero for next row + bindings_[j].buffer = NULL; + bindings_[j].buffer_length = 0; } diff --git a/src/MariaRow.h b/src/MariaRow.h index 553edd02..45efd3b5 100644 --- a/src/MariaRow.h +++ b/src/MariaRow.h @@ -8,41 +8,40 @@ #include "MariaTypes.h" class MariaRow : public boost::noncopyable { - MYSQL_STMT* pStatement_; - - int n_; - std::vector bindings_; - - std::vector types_; - std::vector > buffers_; - std::vector lengths_; - boost::container::vector nulls_, errors_; - -public: - MariaRow(); - ~MariaRow(); - -public: - void setup(MYSQL_STMT* pStatement, - const std::vector& types); - void set_list_value(SEXP x, int i, int j); - -private: - // Value accessors - // ----------------------------------------------------------- - bool is_null(int j); - - int value_int(int j); - int value_bool(int j); - int64_t value_int64(int j); - double value_double(int j); - SEXP value_string(int j); - SEXP value_raw(int j); - double value_date_time(int j); - double value_date(int j); - double value_time(int j); - - void fetch_buffer(int j); + MYSQL_STMT* pStatement_; + + int n_; + std::vector bindings_; + + std::vector types_; + std::vector > buffers_; + std::vector lengths_; + boost::container::vector nulls_, errors_; + + public: + MariaRow(); + ~MariaRow(); + + public: + void setup(MYSQL_STMT* pStatement, const std::vector& types); + void set_list_value(SEXP x, int i, int j); + + private: + // Value accessors + // ----------------------------------------------------------- + bool is_null(int j); + + int value_int(int j); + int value_bool(int j); + int64_t value_int64(int j); + double value_double(int j); + SEXP value_string(int j); + SEXP value_raw(int j); + double value_date_time(int j); + double value_date(int j); + double value_time(int j); + + void fetch_buffer(int j); }; #endif diff --git a/src/MariaTypes.cpp b/src/MariaTypes.cpp index ad420276..cfecffba 100644 --- a/src/MariaTypes.cpp +++ b/src/MariaTypes.cpp @@ -7,157 +7,157 @@ bool all_raw(SEXP x); MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, bool length1) { - switch (type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_YEAR: - return MY_INT32; + switch (type) { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_YEAR: + return MY_INT32; - case MYSQL_TYPE_LONGLONG: - return MY_INT64; + case MYSQL_TYPE_LONGLONG: + return MY_INT64; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - return MY_DBL; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - return MY_DATE_TIME; - case MYSQL_TYPE_DATE: - return MY_DATE; - case MYSQL_TYPE_TIME: - return MY_TIME; - case MYSQL_TYPE_BIT: - if (length1) { - return MY_LGL; - } - // fallthrough - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_SET: - return MY_STR; - case MYSQL_TYPE_GEOMETRY: - return MY_RAW; - case MYSQL_TYPE_NULL: - return MY_INT32; - default: - throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + return MY_DBL; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_NEWDATE: + return MY_DATE_TIME; + case MYSQL_TYPE_DATE: + return MY_DATE; + case MYSQL_TYPE_TIME: + return MY_TIME; + case MYSQL_TYPE_BIT: + if (length1) { + return MY_LGL; } + // fallthrough + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_SET: + return MY_STR; + case MYSQL_TYPE_GEOMETRY: + return MY_RAW; + case MYSQL_TYPE_NULL: + return MY_INT32; + default: + throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); + } } std::string type_name(MariaFieldType type) { - switch (type) { - case MY_INT32: - return "integer"; - case MY_INT64: - return "integer64"; - case MY_DBL: - return "double"; - case MY_STR: - return "string"; - case MY_DATE: - return "Date"; - case MY_DATE_TIME: - return "POSIXct"; - case MY_TIME: - return "hms"; - case MY_RAW: - return "raw"; - case MY_LGL: - return "logical"; - } - throw std::runtime_error("Invalid typeName"); + switch (type) { + case MY_INT32: + return "integer"; + case MY_INT64: + return "integer64"; + case MY_DBL: + return "double"; + case MY_STR: + return "string"; + case MY_DATE: + return "Date"; + case MY_DATE_TIME: + return "POSIXct"; + case MY_TIME: + return "hms"; + case MY_RAW: + return "raw"; + case MY_LGL: + return "logical"; + } + throw std::runtime_error("Invalid typeName"); } SEXPTYPE type_sexp(MariaFieldType type) { - switch (type) { - case MY_INT32: - return INTSXP; - case MY_INT64: - return INT64SXP; - case MY_DBL: - return REALSXP; - case MY_STR: - return STRSXP; - case MY_DATE: - return REALSXP; - case MY_DATE_TIME: - return REALSXP; - case MY_TIME: - return REALSXP; - case MY_RAW: - return VECSXP; - case MY_LGL: - return LGLSXP; - } - throw std::runtime_error("Invalid typeSEXP"); + switch (type) { + case MY_INT32: + return INTSXP; + case MY_INT64: + return INT64SXP; + case MY_DBL: + return REALSXP; + case MY_STR: + return STRSXP; + case MY_DATE: + return REALSXP; + case MY_DATE_TIME: + return REALSXP; + case MY_TIME: + return REALSXP; + case MY_RAW: + return VECSXP; + case MY_LGL: + return LGLSXP; + } + throw std::runtime_error("Invalid typeSEXP"); } std::string r_class(RObject x) { - RObject klass_(x.attr("class")); - std::string klass; - if (klass_ == R_NilValue) - return ""; + RObject klass_(x.attr("class")); + std::string klass; + if (klass_ == R_NilValue) + return ""; - CharacterVector klassv = as(klass_); - return std::string(klassv[klassv.length() - 1]); + CharacterVector klassv = as(klass_); + return std::string(klassv[klassv.length() - 1]); } MariaFieldType variable_type_from_object(const RObject& type) { - std::string klass = r_class(type); + std::string klass = r_class(type); - switch (TYPEOF(type)) { - case LGLSXP: - return MY_LGL; - case INTSXP: - return MY_INT32; - case REALSXP: - if (klass == "Date") - return MY_DATE; - if (klass == "POSIXt") - return MY_DATE_TIME; - if (klass == "difftime") - return MY_TIME; - if (klass == "integer64") - return MY_INT64; - return MY_DBL; - case STRSXP: - return MY_STR; - case VECSXP: - if (klass == "blob") - return MY_RAW; - if (all_raw(type)) - return MY_RAW; - break; - } - - stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); + switch (TYPEOF(type)) { + case LGLSXP: + return MY_LGL; + case INTSXP: + return MY_INT32; + case REALSXP: + if (klass == "Date") + return MY_DATE; + if (klass == "POSIXt") + return MY_DATE_TIME; + if (klass == "difftime") + return MY_TIME; + if (klass == "integer64") + return MY_INT64; + return MY_DBL; + case STRSXP: return MY_STR; + case VECSXP: + if (klass == "blob") + return MY_RAW; + if (all_raw(type)) + return MY_RAW; + break; + } + + stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); + return MY_STR; } bool all_raw(SEXP x) { - List xx(x); - for (R_xlen_t i = 0; i < xx.length(); ++i) { - switch (TYPEOF(xx[i])) { - case RAWSXP: - case NILSXP: - break; + List xx(x); + for (R_xlen_t i = 0; i < xx.length(); ++i) { + switch (TYPEOF(xx[i])) { + case RAWSXP: + case NILSXP: + break; - default: - return false; - } + default: + return false; } - return true; + } + return true; } diff --git a/src/MariaTypes.h b/src/MariaTypes.h index 8d3fd866..df681f7f 100644 --- a/src/MariaTypes.h +++ b/src/MariaTypes.h @@ -2,15 +2,15 @@ #define __RMARIADB_MARIA_TYPES__ enum MariaFieldType { - MY_INT32, - MY_INT64, // output only - MY_DBL, - MY_STR, - MY_DATE, - MY_DATE_TIME, - MY_TIME, - MY_RAW, - MY_LGL // for BIT(1) + MY_INT32, + MY_INT64, // output only + MY_DBL, + MY_STR, + MY_DATE, + MY_DATE_TIME, + MY_TIME, + MY_RAW, + MY_LGL // for BIT(1) }; MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 0aae55fc..d772fcae 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -29,271 +29,270 @@ RcppExport SEXP _RMariaDB_connection_create( SEXP default_fileSEXP, SEXP ssl_keySEXP, SEXP ssl_certSEXP, SEXP ssl_caSEXP, SEXP ssl_capathSEXP, SEXP ssl_cipherSEXP, SEXP timeoutSEXP, SEXP reconnectSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter&>::type host( - hostSEXP); - Rcpp::traits::input_parameter&>::type user( - userSEXP); - Rcpp::traits::input_parameter&>::type password( - passwordSEXP); - Rcpp::traits::input_parameter&>::type db( - dbSEXP); - Rcpp::traits::input_parameter::type port(portSEXP); - Rcpp::traits::input_parameter&>::type - unix_socket(unix_socketSEXP); - Rcpp::traits::input_parameter::type client_flag( - client_flagSEXP); - Rcpp::traits::input_parameter&>::type groups( - groupsSEXP); - Rcpp::traits::input_parameter&>::type - default_file(default_fileSEXP); - Rcpp::traits::input_parameter&>::type ssl_key( - ssl_keySEXP); - Rcpp::traits::input_parameter&>::type ssl_cert( - ssl_certSEXP); - Rcpp::traits::input_parameter&>::type ssl_ca( - ssl_caSEXP); - Rcpp::traits::input_parameter&>::type - ssl_capath(ssl_capathSEXP); - Rcpp::traits::input_parameter&>::type - ssl_cipher(ssl_cipherSEXP); - Rcpp::traits::input_parameter::type timeout(timeoutSEXP); - Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); - rcpp_result_gen = Rcpp::wrap( - connection_create(host, user, password, db, port, unix_socket, - client_flag, groups, default_file, ssl_key, ssl_cert, - ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter&>::type host( + hostSEXP); + Rcpp::traits::input_parameter&>::type user( + userSEXP); + Rcpp::traits::input_parameter&>::type password( + passwordSEXP); + Rcpp::traits::input_parameter&>::type db(dbSEXP); + Rcpp::traits::input_parameter::type port(portSEXP); + Rcpp::traits::input_parameter&>::type unix_socket( + unix_socketSEXP); + Rcpp::traits::input_parameter::type client_flag( + client_flagSEXP); + Rcpp::traits::input_parameter&>::type groups( + groupsSEXP); + Rcpp::traits::input_parameter&>::type + default_file(default_fileSEXP); + Rcpp::traits::input_parameter&>::type ssl_key( + ssl_keySEXP); + Rcpp::traits::input_parameter&>::type ssl_cert( + ssl_certSEXP); + Rcpp::traits::input_parameter&>::type ssl_ca( + ssl_caSEXP); + Rcpp::traits::input_parameter&>::type ssl_capath( + ssl_capathSEXP); + Rcpp::traits::input_parameter&>::type ssl_cipher( + ssl_cipherSEXP); + Rcpp::traits::input_parameter::type timeout(timeoutSEXP); + Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); + rcpp_result_gen = Rcpp::wrap( + connection_create(host, user, password, db, port, unix_socket, + client_flag, groups, default_file, ssl_key, ssl_cert, + ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); + return rcpp_result_gen; + END_RCPP } // connection_valid bool connection_valid(XPtr con_); RcppExport SEXP _RMariaDB_connection_valid(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); + return rcpp_result_gen; + END_RCPP } // connection_release void connection_release(XPtr con_); RcppExport SEXP _RMariaDB_connection_release(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - connection_release(con_); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + connection_release(con_); + return R_NilValue; + END_RCPP } // connection_info List connection_info(DbConnection* con); RcppExport SEXP _RMariaDB_connection_info(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_info(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_info(con)); + return rcpp_result_gen; + END_RCPP } // connection_quote_string CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs); RcppExport SEXP _RMariaDB_connection_quote_string(SEXP conSEXP, SEXP xsSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - Rcpp::traits::input_parameter::type xs(xsSEXP); - rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + Rcpp::traits::input_parameter::type xs(xsSEXP); + rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); + return rcpp_result_gen; + END_RCPP } // connection_begin_transaction void connection_begin_transaction(XPtr con); RcppExport SEXP _RMariaDB_connection_begin_transaction(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_begin_transaction(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_begin_transaction(con); + return R_NilValue; + END_RCPP } // connection_commit void connection_commit(XPtr con); RcppExport SEXP _RMariaDB_connection_commit(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_commit(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_commit(con); + return R_NilValue; + END_RCPP } // connection_rollback void connection_rollback(XPtr con); RcppExport SEXP _RMariaDB_connection_rollback(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_rollback(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_rollback(con); + return R_NilValue; + END_RCPP } // connection_is_transacting bool connection_is_transacting(DbConnection* con); RcppExport SEXP _RMariaDB_connection_is_transacting(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); + return rcpp_result_gen; + END_RCPP } // driver_init void driver_init(); RcppExport SEXP _RMariaDB_driver_init() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_init(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_init(); + return R_NilValue; + END_RCPP } // driver_done void driver_done(); RcppExport SEXP _RMariaDB_driver_done() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_done(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_done(); + return R_NilValue; + END_RCPP } // version IntegerVector version(); RcppExport SEXP _RMariaDB_version() { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - rcpp_result_gen = Rcpp::wrap(version()); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = Rcpp::wrap(version()); + return rcpp_result_gen; + END_RCPP } // init_logging void init_logging(const std::string& log_level); RcppExport SEXP _RMariaDB_init_logging(SEXP log_levelSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type log_level( - log_levelSEXP); - init_logging(log_level); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type log_level( + log_levelSEXP); + init_logging(log_level); + return R_NilValue; + END_RCPP } // result_create XPtr result_create(XPtr con, std::string sql, bool is_statement); RcppExport SEXP _RMariaDB_result_create(SEXP conSEXP, SEXP sqlSEXP, SEXP is_statementSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - Rcpp::traits::input_parameter::type sql(sqlSEXP); - Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); - rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + Rcpp::traits::input_parameter::type sql(sqlSEXP); + Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); + rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); + return rcpp_result_gen; + END_RCPP } // result_release void result_release(XPtr res); RcppExport SEXP _RMariaDB_result_release(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res(resSEXP); - result_release(res); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res(resSEXP); + result_release(res); + return R_NilValue; + END_RCPP } // result_valid bool result_valid(XPtr res_); RcppExport SEXP _RMariaDB_result_valid(SEXP res_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res_(res_SEXP); - rcpp_result_gen = Rcpp::wrap(result_valid(res_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res_(res_SEXP); + rcpp_result_gen = Rcpp::wrap(result_valid(res_)); + return rcpp_result_gen; + END_RCPP } // result_fetch List result_fetch(DbResult* res, const int n); RcppExport SEXP _RMariaDB_result_fetch(SEXP resSEXP, SEXP nSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type n(nSEXP); - rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type n(nSEXP); + rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); + return rcpp_result_gen; + END_RCPP } // result_bind void result_bind(DbResult* res, List params); RcppExport SEXP _RMariaDB_result_bind(SEXP resSEXP, SEXP paramsSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type params(paramsSEXP); - result_bind(res, params); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type params(paramsSEXP); + result_bind(res, params); + return R_NilValue; + END_RCPP } // result_has_completed bool result_has_completed(DbResult* res); RcppExport SEXP _RMariaDB_result_has_completed(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_fetched int result_rows_fetched(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_fetched(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_affected int result_rows_affected(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_affected(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); + return rcpp_result_gen; + END_RCPP } // result_column_info List result_column_info(DbResult* res); RcppExport SEXP _RMariaDB_result_column_info(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_column_info(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_column_info(res)); + return rcpp_result_gen; + END_RCPP } static const R_CallMethodDef CallEntries[] = { @@ -329,6 +328,6 @@ static const R_CallMethodDef CallEntries[] = { {NULL, NULL, 0}}; RcppExport void R_init_RMariaDB(DllInfo* dll) { - R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); - R_useDynamicSymbols(dll, FALSE); + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); } diff --git a/src/connection.cpp b/src/connection.cpp index 7a8d17af..6f1ac842 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -12,81 +12,81 @@ XPtr connection_create( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; + LOG_VERBOSE; - DbConnection* pConnPtr = new DbConnection; - try { - pConnPtr->connect(host, user, password, db, port, unix_socket, - client_flag, groups, default_file, ssl_key, ssl_cert, - ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect); - } catch (...) { - delete pConnPtr; - throw; - } + DbConnection* pConnPtr = new DbConnection; + try { + pConnPtr->connect(host, user, password, db, port, unix_socket, client_flag, + groups, default_file, ssl_key, ssl_cert, ssl_ca, + ssl_capath, ssl_cipher, timeout, reconnect); + } catch (...) { + delete pConnPtr; + throw; + } - DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); + DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); - return XPtr(pConn, true); + return XPtr(pConn, true); } // [[Rcpp::export]] bool connection_valid(XPtr con_) { - DbConnectionPtr* con = con_.get(); - return con && con->get()->is_valid(); + DbConnectionPtr* con = con_.get(); + return con && con->get()->is_valid(); } // [[Rcpp::export]] void connection_release(XPtr con_) { - if (!connection_valid(con_)) { - warning("Already disconnected"); - return; - } - - DbConnectionPtr* con = con_.get(); - con->get()->disconnect(); - con_.release(); + if (!connection_valid(con_)) { + warning("Already disconnected"); + return; + } + + DbConnectionPtr* con = con_.get(); + con->get()->disconnect(); + con_.release(); } // [[Rcpp::export]] List connection_info(DbConnection* con) { - return con->info(); + return con->info(); } // Quoting // [[Rcpp::export]] CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs) { - R_xlen_t n = xs.size(); - CharacterVector output(n); + R_xlen_t n = xs.size(); + CharacterVector output(n); - for (R_xlen_t i = 0; i < n; ++i) { - String x = xs[i]; - output[i] = con->quote_string(x); - } + for (R_xlen_t i = 0; i < n; ++i) { + String x = xs[i]; + output[i] = con->quote_string(x); + } - return output; + return output; } // Transactions // [[Rcpp::export]] void connection_begin_transaction(XPtr con) { - (*con)->begin_transaction(); + (*con)->begin_transaction(); } // [[Rcpp::export]] void connection_commit(XPtr con) { - (*con)->commit(); + (*con)->commit(); } // [[Rcpp::export]] void connection_rollback(XPtr con) { - (*con)->rollback(); + (*con)->rollback(); } // [[Rcpp::export]] bool connection_is_transacting(DbConnection* con) { - return con->is_transacting(); + return con->is_transacting(); } // Specific functions @@ -97,10 +97,10 @@ namespace Rcpp { template <> DbConnection* as(SEXP x) { - DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); - if (!connection) - stop("Invalid connection"); - return connection->get(); + DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); + if (!connection) + stop("Invalid connection"); + return connection->get(); } } // namespace Rcpp diff --git a/src/driver.cpp b/src/driver.cpp index 5c05fbbe..aa940f86 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -10,22 +10,22 @@ // [[Rcpp::export]] void driver_init() { - mysql_library_init(0, NULL, NULL); + mysql_library_init(0, NULL, NULL); } // [[Rcpp::export]] void driver_done() { - mysql_library_end(); + mysql_library_end(); } // [[Rcpp::export]] IntegerVector version() { - return IntegerVector::create( - _[SERVER_VERSION] = MYSQL_VERSION_ID, - _[mysql_get_client_info()] = mysql_get_client_version()); + return IntegerVector::create( + _[SERVER_VERSION] = MYSQL_VERSION_ID, + _[mysql_get_client_info()] = mysql_get_client_version()); } // [[Rcpp::export]] void init_logging(const std::string& log_level) { - plog::init_r(log_level); + plog::init_r(log_level); } diff --git a/src/integer64.h b/src/integer64.h index 2b0a6f42..2f3b934c 100644 --- a/src/integer64.h +++ b/src/integer64.h @@ -6,7 +6,7 @@ #define NA_INTEGER64 (static_cast(0x8000000000000000)) inline int64_t* INTEGER64(SEXP x) { - return reinterpret_cast(REAL(x)); + return reinterpret_cast(REAL(x)); } #endif // RMARIADB_INTEGER64_H diff --git a/src/result.cpp b/src/result.cpp index 38a448fa..16a8aa4a 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -5,60 +5,60 @@ // [[Rcpp::export]] XPtr result_create(XPtr con, std::string sql, bool is_statement = false) { - (*con)->check_connection(); - DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); - return XPtr(res, true); + (*con)->check_connection(); + DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); + return XPtr(res, true); } // [[Rcpp::export]] void result_release(XPtr res) { - res.release(); + res.release(); } // [[Rcpp::export]] bool result_valid(XPtr res_) { - DbResult* res = res_.get(); - return res != NULL && res->is_active(); + DbResult* res = res_.get(); + return res != NULL && res->is_active(); } // [[Rcpp::export]] List result_fetch(DbResult* res, const int n) { - return res->fetch(n); + return res->fetch(n); } // [[Rcpp::export]] void result_bind(DbResult* res, List params) { - res->bind(params); + res->bind(params); } // [[Rcpp::export]] bool result_has_completed(DbResult* res) { - return res->complete(); + return res->complete(); } // [[Rcpp::export]] int result_rows_fetched(DbResult* res) { - return res->n_rows_fetched(); + return res->n_rows_fetched(); } // [[Rcpp::export]] int result_rows_affected(DbResult* res) { - return res->n_rows_affected(); + return res->n_rows_affected(); } // [[Rcpp::export]] List result_column_info(DbResult* res) { - return res->get_column_info(); + return res->get_column_info(); } namespace Rcpp { template <> DbResult* as(SEXP x) { - DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); - if (!result) - stop("Invalid result set"); - return result; + DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); + if (!result) + stop("Invalid result set"); + return result; } } // namespace Rcpp From 15c3543d83902b5db18597aceade5cb9dbb5065c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 21 Nov 2022 15:50:44 +0000 Subject: [PATCH 7/9] update indent --- .clang-format | 4 +- src/DbConnection.cpp | 269 ++++++++++++------------ src/DbConnection.h | 90 ++++---- src/DbResult.cpp | 69 ++++--- src/DbResult.h | 36 ++-- src/MariaBinding.cpp | 424 +++++++++++++++++++------------------- src/MariaBinding.h | 42 ++-- src/MariaResult.cpp | 26 +-- src/MariaResult.h | 18 +- src/MariaResultImpl.h | 24 +-- src/MariaResultPrep.cpp | 323 ++++++++++++++--------------- src/MariaResultPrep.h | 66 +++--- src/MariaResultSimple.cpp | 46 ++--- src/MariaResultSimple.h | 30 +-- src/MariaRow.cpp | 380 +++++++++++++++++----------------- src/MariaRow.h | 69 ++++--- src/MariaTypes.cpp | 260 +++++++++++------------ src/MariaTypes.h | 18 +- src/RcppExports.cpp | 361 ++++++++++++++++---------------- src/connection.cpp | 76 +++---- src/driver.cpp | 12 +- src/integer64.h | 2 +- src/result.cpp | 32 +-- 23 files changed, 1341 insertions(+), 1336 deletions(-) diff --git a/.clang-format b/.clang-format index 037de4f9..8dd36a13 100644 --- a/.clang-format +++ b/.clang-format @@ -1,9 +1,9 @@ BasedOnStyle: Google Language: Cpp TabWidth: 4 -IndentWidth: 2 +IndentWidth: 4 UseTab: ForIndentation IndentCaseLabels: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never -AccessModifierOffset: -4 \ No newline at end of file +AccessModifierOffset: -4 diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index d1447e85..d02ffe58 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -5,16 +5,16 @@ DbConnection::DbConnection() : pConn_(NULL), pCurrentResult_(NULL), transacting_(false) { - LOG_VERBOSE; + LOG_VERBOSE; } DbConnection::~DbConnection() { - LOG_VERBOSE; + LOG_VERBOSE; - if (is_valid()) { - warning("call dbDisconnect() when finished working with a connection"); - disconnect(); - } + if (is_valid()) { + warning("call dbDisconnect() when finished working with a connection"); + disconnect(); + } } void DbConnection::connect( @@ -27,200 +27,201 @@ void DbConnection::connect( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; - - this->pConn_ = mysql_init(NULL); - // Enable LOCAL INFILE for fast data ingest - unsigned int local_infile = 1; - mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); - // Default to UTF-8 - mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); - if (!groups.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, - as(groups).c_str()); - if (!default_file.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, - as(default_file).c_str()); - - if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || - !ssl_capath.isNull() || !ssl_cipher.isNull()) { - mysql_ssl_set( - this->pConn_, - ssl_key.isNull() ? NULL : as(ssl_key).c_str(), - ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), - ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), - ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), - ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); - } - if (timeout > 0) { - mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); - } - if (reconnect) { - my_bool reconnect_ = 1; - mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); - } - - LOG_VERBOSE; - - if (!mysql_real_connect( - this->pConn_, host.isNull() ? NULL : as(host).c_str(), - user.isNull() ? NULL : as(user).c_str(), - password.isNull() ? NULL : as(password).c_str(), - db.isNull() ? NULL : as(db).c_str(), port, - unix_socket.isNull() ? NULL : as(unix_socket).c_str(), - client_flag)) { - std::string error = mysql_error(this->pConn_); - mysql_close(this->pConn_); - this->pConn_ = NULL; - - stop("Failed to connect: %s", error.c_str()); - } + LOG_VERBOSE; + + this->pConn_ = mysql_init(NULL); + // Enable LOCAL INFILE for fast data ingest + unsigned int local_infile = 1; + mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); + // Default to UTF-8 + mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); + if (!groups.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, + as(groups).c_str()); + if (!default_file.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, + as(default_file).c_str()); + + if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || + !ssl_capath.isNull() || !ssl_cipher.isNull()) { + mysql_ssl_set( + this->pConn_, + ssl_key.isNull() ? NULL : as(ssl_key).c_str(), + ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), + ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), + ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), + ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); + } + if (timeout > 0) { + mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); + } + if (reconnect) { + my_bool reconnect_ = 1; + mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); + } + + LOG_VERBOSE; + + if (!mysql_real_connect( + this->pConn_, host.isNull() ? NULL : as(host).c_str(), + user.isNull() ? NULL : as(user).c_str(), + password.isNull() ? NULL : as(password).c_str(), + db.isNull() ? NULL : as(db).c_str(), port, + unix_socket.isNull() ? NULL : as(unix_socket).c_str(), + client_flag)) { + std::string error = mysql_error(this->pConn_); + mysql_close(this->pConn_); + this->pConn_ = NULL; + + stop("Failed to connect: %s", error.c_str()); + } } void DbConnection::disconnect() { - if (!is_valid()) - return; + if (!is_valid()) + return; - if (has_query()) { - warning("%s\n%s", "There is a result object still in use.", - "The connection will be automatically released when it is closed"); - } + if (has_query()) { + warning( + "%s\n%s", "There is a result object still in use.", + "The connection will be automatically released when it is closed"); + } - try { - mysql_close(get_conn()); - } catch (...) { - }; + try { + mysql_close(get_conn()); + } catch (...) { + }; - pConn_ = NULL; + pConn_ = NULL; } bool DbConnection::is_valid() { - return !!get_conn(); + return !!get_conn(); } void DbConnection::check_connection() { - if (!is_valid()) { - stop("Invalid or closed connection"); - } + if (!is_valid()) { + stop("Invalid or closed connection"); + } } List DbConnection::info() { - return List::create( - _["host"] = std::string(pConn_->host), - _["username"] = std::string(pConn_->user), - _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), - _["con.type"] = std::string(mysql_get_host_info(pConn_)), - _["db.version"] = std::string(mysql_get_server_info(pConn_)), - _["port"] = NA_INTEGER, - _["protocol.version"] = (int)mysql_get_proto_info(pConn_), - _["thread.id"] = (int)mysql_thread_id(pConn_)); + return List::create( + _["host"] = std::string(pConn_->host), + _["username"] = std::string(pConn_->user), + _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), + _["con.type"] = std::string(mysql_get_host_info(pConn_)), + _["db.version"] = std::string(mysql_get_server_info(pConn_)), + _["port"] = NA_INTEGER, + _["protocol.version"] = (int)mysql_get_proto_info(pConn_), + _["thread.id"] = (int)mysql_thread_id(pConn_)); } MYSQL* DbConnection::get_conn() { - return pConn_; + return pConn_; } SEXP DbConnection::quote_string(const String& input) { - if (input == NA_STRING) - return get_null_string(); + if (input == NA_STRING) + return get_null_string(); - const char* input_cstr = input.get_cstring(); - size_t input_len = strlen(input_cstr); + const char* input_cstr = input.get_cstring(); + size_t input_len = strlen(input_cstr); - // Create buffer with enough room to escape every character - std::string output = "'"; - output.resize(input_len * 2 + 3); + // Create buffer with enough room to escape every character + std::string output = "'"; + output.resize(input_len * 2 + 3); - size_t end = - mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); + size_t end = + mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); - output.resize(end + 1); - output.append("'"); - return Rf_mkCharCE(output.c_str(), CE_UTF8); + output.resize(end + 1); + output.append("'"); + return Rf_mkCharCE(output.c_str(), CE_UTF8); } SEXP DbConnection::get_null_string() { - static RObject null = Rf_mkCharCE("NULL", CE_UTF8); - return null; + static RObject null = Rf_mkCharCE("NULL", CE_UTF8); + return null; } void DbConnection::set_current_result(DbResult* pResult) { - if (pResult == pCurrentResult_) - return; + if (pResult == pCurrentResult_) + return; - if (pCurrentResult_ != NULL) { - if (pResult != NULL) - warning("Cancelling previous query"); + if (pCurrentResult_ != NULL) { + if (pResult != NULL) + warning("Cancelling previous query"); - pCurrentResult_->close(); - } - pCurrentResult_ = pResult; + pCurrentResult_->close(); + } + pCurrentResult_ = pResult; } void DbConnection::reset_current_result(DbResult* pResult) { - // FIXME: What to do if not current result is reset? - if (pResult != pCurrentResult_) - return; + // FIXME: What to do if not current result is reset? + if (pResult != pCurrentResult_) + return; - pCurrentResult_->close(); - pCurrentResult_ = NULL; + pCurrentResult_->close(); + pCurrentResult_ = NULL; } bool DbConnection::is_current_result(const DbResult* pResult) const { - return pCurrentResult_ == pResult; + return pCurrentResult_ == pResult; } bool DbConnection::has_query() { - return pCurrentResult_ != NULL; + return pCurrentResult_ != NULL; } bool DbConnection::exec(const std::string& sql) { - check_connection(); + check_connection(); - if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) - stop("Error executing query: %s", mysql_error(pConn_)); + if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) + stop("Error executing query: %s", mysql_error(pConn_)); - MYSQL_RES* res = mysql_store_result(pConn_); - if (res != NULL) - mysql_free_result(res); + MYSQL_RES* res = mysql_store_result(pConn_); + if (res != NULL) + mysql_free_result(res); - autocommit(); + autocommit(); - return true; + return true; } void DbConnection::begin_transaction() { - if (is_transacting()) - stop("Nested transactions not supported."); - check_connection(); + if (is_transacting()) + stop("Nested transactions not supported."); + check_connection(); - transacting_ = true; + transacting_ = true; } void DbConnection::commit() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_commit(get_conn()); - transacting_ = false; + mysql_commit(get_conn()); + transacting_ = false; } void DbConnection::rollback() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_rollback(get_conn()); - transacting_ = false; + mysql_rollback(get_conn()); + transacting_ = false; } bool DbConnection::is_transacting() const { - return transacting_; + return transacting_; } void DbConnection::autocommit() { - if (!is_transacting() && get_conn()) { - mysql_commit(get_conn()); - } + if (!is_transacting() && get_conn()) { + mysql_commit(get_conn()); + } } diff --git a/src/DbConnection.h b/src/DbConnection.h index c166a857..e9179e94 100644 --- a/src/DbConnection.h +++ b/src/DbConnection.h @@ -11,51 +11,51 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class DbConnection : boost::noncopyable { - MYSQL* pConn_; - DbResult* pCurrentResult_; - bool transacting_; - - public: - DbConnection(); - ~DbConnection(); - - public: - void connect(const Nullable& host, - const Nullable& user, - const Nullable& password, - const Nullable& db, unsigned int port, - const Nullable& unix_socket, - unsigned long client_flag, const Nullable& groups, - const Nullable& default_file, - const Nullable& ssl_key, - const Nullable& ssl_cert, - const Nullable& ssl_ca, - const Nullable& ssl_capath, - const Nullable& ssl_cipher, int timeout, - bool reconnect); - void disconnect(); - bool is_valid(); - void check_connection(); - - List info(); - MYSQL* get_conn(); - - SEXP quote_string(const String& input); - static SEXP get_null_string(); - - // Cancels previous query, if needed. - void set_current_result(DbResult* pResult); - void reset_current_result(DbResult* pResult); - bool is_current_result(const DbResult* pResult) const; - bool has_query(); - - bool exec(const std::string& sql); - - void begin_transaction(); - void commit(); - void rollback(); - bool is_transacting() const; - void autocommit(); + MYSQL* pConn_; + DbResult* pCurrentResult_; + bool transacting_; + +public: + DbConnection(); + ~DbConnection(); + +public: + void connect(const Nullable& host, + const Nullable& user, + const Nullable& password, + const Nullable& db, unsigned int port, + const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, + const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, + bool reconnect); + void disconnect(); + bool is_valid(); + void check_connection(); + + List info(); + MYSQL* get_conn(); + + SEXP quote_string(const String& input); + static SEXP get_null_string(); + + // Cancels previous query, if needed. + void set_current_result(DbResult* pResult); + void reset_current_result(DbResult* pResult); + bool is_current_result(const DbResult* pResult) const; + bool has_query(); + + bool exec(const std::string& sql); + + void begin_transaction(); + void commit(); + void rollback(); + bool is_transacting() const; + void autocommit(); }; #endif diff --git a/src/DbResult.cpp b/src/DbResult.cpp index af53a890..440c111a 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -7,78 +7,79 @@ // Construction //////////////////////////////////////////////////////////////// DbResult::DbResult(const DbConnectionPtr& pConn) : pConn_(pConn) { - pConn_->check_connection(); + pConn_->check_connection(); - // subclass constructor can throw, the destructor will remove the - // current result set - pConn_->set_current_result(this); + // subclass constructor can throw, the destructor will remove the + // current result set + pConn_->set_current_result(this); } DbResult::~DbResult() { - try { - if (is_active()) { - pConn_->reset_current_result(this); + try { + if (is_active()) { + pConn_->reset_current_result(this); + } + } catch (...) { } - } catch (...) { - } } // Publics ///////////////////////////////////////////////////////////////////// bool DbResult::complete() const { - return (impl == NULL) || impl->complete(); + return (impl == NULL) || impl->complete(); } bool DbResult::is_active() const { - return pConn_->is_current_result(this); + return pConn_->is_current_result(this); } int DbResult::n_rows_fetched() { - return impl->n_rows_fetched(); + return impl->n_rows_fetched(); } int DbResult::n_rows_affected() { - return impl->n_rows_affected(); + return impl->n_rows_affected(); } void DbResult::bind(const List& params) { - validate_params(params); - impl->bind(params); + validate_params(params); + impl->bind(params); } List DbResult::fetch(const int n_max) { - if (!is_active()) - stop("Inactive result set"); + if (!is_active()) + stop("Inactive result set"); - return impl->fetch(n_max); + return impl->fetch(n_max); } List DbResult::get_column_info() { - List out = impl->get_column_info(); + List out = impl->get_column_info(); - out.attr("row.names") = IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); - out.attr("class") = "data.frame"; + out.attr("row.names") = + IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); + out.attr("class") = "data.frame"; - return out; + return out; } void DbResult::close() { - // Called from destructor - if (impl) - impl->close(); + // Called from destructor + if (impl) + impl->close(); } // Privates /////////////////////////////////////////////////////////////////// void DbResult::validate_params(const List& params) const { - if (params.size() != 0) { - SEXP first_col = params[0]; - int n = Rf_length(first_col); - - for (int j = 1; j < params.size(); ++j) { - SEXP col = params[j]; - if (Rf_length(col) != n) - stop("Parameter %i does not have length %d.", j + 1, n); + if (params.size() != 0) { + SEXP first_col = params[0]; + int n = Rf_length(first_col); + + for (int j = 1; j < params.size(); ++j) { + SEXP col = params[j]; + if (Rf_length(col) != n) + stop("Parameter %i does not have length %d.", j + 1, n); + } } - } } diff --git a/src/DbResult.h b/src/DbResult.h index 625e54e7..96fb8ecb 100644 --- a/src/DbResult.h +++ b/src/DbResult.h @@ -13,32 +13,32 @@ typedef boost::shared_ptr DbConnectionPtr; // DbResult -------------------------------------------------------------------- class DbResult : boost::noncopyable { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - protected: - boost::scoped_ptr impl; +protected: + boost::scoped_ptr impl; - protected: - DbResult(const DbConnectionPtr& pConn); +protected: + DbResult(const DbConnectionPtr& pConn); - public: - ~DbResult(); +public: + ~DbResult(); - public: - void close(); +public: + void close(); - bool complete() const; - bool is_active() const; - int n_rows_fetched(); - int n_rows_affected(); + bool complete() const; + bool is_active() const; + int n_rows_fetched(); + int n_rows_affected(); - void bind(const List& params); - List fetch(int n_max = -1); + void bind(const List& params); + List fetch(int n_max = -1); - List get_column_info(); + List get_column_info(); - private: - void validate_params(const List& params) const; +private: + void validate_params(const List& params) const; }; #endif // __RDBI_DB_RESULT__ diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index 59f52d87..7ebf3703 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -12,253 +12,253 @@ MariaBinding::~MariaBinding() { } void MariaBinding::setup(MYSQL_STMT* statement_) { - LOG_VERBOSE; + LOG_VERBOSE; - statement = statement_; - p = static_cast(mysql_stmt_param_count(statement)); + statement = statement_; + p = static_cast(mysql_stmt_param_count(statement)); - bindings.resize(p); - types.resize(p); - is_null.resize(p); - time_buffers.resize(p); + bindings.resize(p); + types.resize(p); + is_null.resize(p); + time_buffers.resize(p); } void MariaBinding::init_binding(const List& params_) { - LOG_VERBOSE; + LOG_VERBOSE; - params = params_; + params = params_; - if (params.size() == 0) { - stop("Query has no parameters"); - } + if (params.size() == 0) { + stop("Query has no parameters"); + } - if (p != params.size()) { - stop("Number of params don't match (%i vs %i)", p, params.size()); - } + if (p != params.size()) { + stop("Number of params don't match (%i vs %i)", p, params.size()); + } - i = 0; + i = 0; - for (int j = 0; j < p; ++j) { - RObject param(params[j]); - MariaFieldType type = variable_type_from_object(param); - types[j] = type; + for (int j = 0; j < p; ++j) { + RObject param(params[j]); + MariaFieldType type = variable_type_from_object(param); + types[j] = type; - LOG_VERBOSE << j << " -> " << type_name(type); + LOG_VERBOSE << j << " -> " << type_name(type); - if (j == 0) { - n_rows = Rf_xlength(param); - } + if (j == 0) { + n_rows = Rf_xlength(param); + } - switch (type) { - case MY_LGL: - binding_update(j, MYSQL_TYPE_TINY, 1); - break; - case MY_INT32: - binding_update(j, MYSQL_TYPE_LONG, 4); - break; - case MY_DBL: - binding_update(j, MYSQL_TYPE_DOUBLE, 8); - break; - case MY_DATE: - binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); - break; - case MY_TIME: - binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); - break; - case MY_STR: - binding_update(j, MYSQL_TYPE_STRING, 0); - break; - case MY_RAW: - binding_update(j, MYSQL_TYPE_BLOB, 0); - break; - case MY_INT64: - binding_update(j, MYSQL_TYPE_LONGLONG, 0); - break; + switch (type) { + case MY_LGL: + binding_update(j, MYSQL_TYPE_TINY, 1); + break; + case MY_INT32: + binding_update(j, MYSQL_TYPE_LONG, 4); + break; + case MY_DBL: + binding_update(j, MYSQL_TYPE_DOUBLE, 8); + break; + case MY_DATE: + binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); + break; + case MY_TIME: + binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); + break; + case MY_STR: + binding_update(j, MYSQL_TYPE_STRING, 0); + break; + case MY_RAW: + binding_update(j, MYSQL_TYPE_BLOB, 0); + break; + case MY_INT64: + binding_update(j, MYSQL_TYPE_LONGLONG, 0); + break; + } } - } } bool MariaBinding::bind_next_row() { - LOG_VERBOSE; - - if (i >= n_rows) - return false; - - for (int j = 0; j < p; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types[j]); - - bool missing = false; - RObject col(params[j]); - - switch (types[j]) { - case MY_LGL: - if (LOGICAL(col)[i] == NA_LOGICAL) { - missing = true; - break; - } - bindings[j].buffer = &LOGICAL(col)[i]; - break; - case MY_INT32: - if (INTEGER(col)[i] == NA_INTEGER) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER(col)[i]; - break; - case MY_DBL: - if (ISNA(REAL(col)[i])) { - missing = true; - break; - } - bindings[j].buffer = &REAL(col)[i]; - break; - case MY_STR: - if (STRING_ELT(col, i) == NA_STRING) { - missing = true; - break; - } else { - SEXP string = STRING_ELT(col, i); - bindings[j].buffer = const_cast(CHAR(string)); - bindings[j].buffer_length = Rf_length(string); - } - break; - case MY_RAW: { - SEXP raw = VECTOR_ELT(col, i); - if (Rf_isNull(raw)) { - missing = true; - } else { - bindings[j].buffer_length = Rf_length(raw); - bindings[j].buffer = RAW(raw); - } - break; - } - case MY_DATE: - case MY_DATE_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - } else { - double val = REAL(col)[i]; - LOG_VERBOSE << val; - if (types[j] == MY_DATE) { - set_date_buffer(j, static_cast(::floor(val))); - clear_time_buffer(j); - } else { - double days = ::floor(val / 86400.0); - set_date_buffer(j, static_cast(days)); - set_time_buffer(j, val - days * 86400.0); + LOG_VERBOSE; + + if (i >= n_rows) + return false; + + for (int j = 0; j < p; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types[j]); + + bool missing = false; + RObject col(params[j]); + + switch (types[j]) { + case MY_LGL: + if (LOGICAL(col)[i] == NA_LOGICAL) { + missing = true; + break; + } + bindings[j].buffer = &LOGICAL(col)[i]; + break; + case MY_INT32: + if (INTEGER(col)[i] == NA_INTEGER) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER(col)[i]; + break; + case MY_DBL: + if (ISNA(REAL(col)[i])) { + missing = true; + break; + } + bindings[j].buffer = &REAL(col)[i]; + break; + case MY_STR: + if (STRING_ELT(col, i) == NA_STRING) { + missing = true; + break; + } else { + SEXP string = STRING_ELT(col, i); + bindings[j].buffer = const_cast(CHAR(string)); + bindings[j].buffer_length = Rf_length(string); + } + break; + case MY_RAW: { + SEXP raw = VECTOR_ELT(col, i); + if (Rf_isNull(raw)) { + missing = true; + } else { + bindings[j].buffer_length = Rf_length(raw); + bindings[j].buffer = RAW(raw); + } + break; + } + case MY_DATE: + case MY_DATE_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + } else { + double val = REAL(col)[i]; + LOG_VERBOSE << val; + if (types[j] == MY_DATE) { + set_date_buffer(j, static_cast(::floor(val))); + clear_time_buffer(j); + } else { + double days = ::floor(val / 86400.0); + set_date_buffer(j, static_cast(days)); + set_time_buffer(j, val - days * 86400.0); + } + LOG_VERBOSE; + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + break; + } else { + double val = REAL(col)[i]; + clear_date_buffer(j); + set_time_buffer(j, val); + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_INT64: + if (INTEGER64(col)[i] == NA_INTEGER64) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER64(col)[i]; + break; } - LOG_VERBOSE; - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - break; - } else { - double val = REAL(col)[i]; - clear_date_buffer(j); - set_time_buffer(j, val); - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_INT64: - if (INTEGER64(col)[i] == NA_INTEGER64) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER64(col)[i]; - break; + is_null[j] = missing; } - is_null[j] = missing; - } - LOG_DEBUG << "Binding"; - mysql_stmt_bind_param(statement, &bindings[0]); + LOG_DEBUG << "Binding"; + mysql_stmt_bind_param(statement, &bindings[0]); - LOG_DEBUG << "Done binding row " << i; - i++; - return true; + LOG_DEBUG << "Done binding row " << i; + i++; + return true; } void MariaBinding::binding_update(int j, enum_field_types type, int size) { - LOG_VERBOSE << j << ", " << type << ", " << size; + LOG_VERBOSE << j << ", " << type << ", " << size; - bindings[j].buffer_length = size; - bindings[j].buffer_type = type; - bindings[j].is_null = &is_null[j]; + bindings[j].buffer_length = size; + bindings[j].buffer_type = type; + bindings[j].is_null = &is_null[j]; } void MariaBinding::clear_date_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].year = 0; - time_buffers[j].month = 0; - time_buffers[j].day = 0; + LOG_VERBOSE << j; + time_buffers[j].year = 0; + time_buffers[j].month = 0; + time_buffers[j].day = 0; } void MariaBinding::set_date_buffer(int j, const int date) { - LOG_VERBOSE << date; - - // https://howardhinnant.github.io/date_algorithms.html#civil_from_days - const int date_0 = date + 719468; - const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; - const unsigned doe = - static_cast(date_0 - era * 146097); // [0, 146096] - LOG_VERBOSE << doe; - const unsigned yoe = - (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] - LOG_VERBOSE << yoe; - const int y = static_cast(yoe) + era * 400; - const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] - const unsigned mp = (5 * doy + 2) / 153; // [0, 11] - const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] - const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] - const unsigned yr = y + (m <= 2); - - // gmtime() fails for dates < 1970 on Windows - LOG_VERBOSE << date_0; - LOG_VERBOSE << yr; - LOG_VERBOSE << m; - LOG_VERBOSE << d; - - time_buffers[j].year = yr; - time_buffers[j].month = m; - time_buffers[j].day = d; + LOG_VERBOSE << date; + + // https://howardhinnant.github.io/date_algorithms.html#civil_from_days + const int date_0 = date + 719468; + const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; + const unsigned doe = + static_cast(date_0 - era * 146097); // [0, 146096] + LOG_VERBOSE << doe; + const unsigned yoe = + (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] + LOG_VERBOSE << yoe; + const int y = static_cast(yoe) + era * 400; + const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] + const unsigned mp = (5 * doy + 2) / 153; // [0, 11] + const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] + const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] + const unsigned yr = y + (m <= 2); + + // gmtime() fails for dates < 1970 on Windows + LOG_VERBOSE << date_0; + LOG_VERBOSE << yr; + LOG_VERBOSE << m; + LOG_VERBOSE << d; + + time_buffers[j].year = yr; + time_buffers[j].month = m; + time_buffers[j].day = d; } void MariaBinding::clear_time_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].hour = 0; - time_buffers[j].minute = 0; - time_buffers[j].second = 0; - time_buffers[j].second_part = 0; - time_buffers[j].neg = 0; + LOG_VERBOSE << j; + time_buffers[j].hour = 0; + time_buffers[j].minute = 0; + time_buffers[j].second = 0; + time_buffers[j].second_part = 0; + time_buffers[j].neg = 0; } void MariaBinding::set_time_buffer(int j, double time) { - LOG_VERBOSE << time; - - bool neg = false; - if (time < 0) { - neg = true; - time = -time; - } - double whole_seconds = ::trunc(time); - double frac_seconds = time - whole_seconds; - double whole_minutes = ::trunc(time / 60.0); - double seconds = whole_seconds - whole_minutes * 60.0; - double hours = ::trunc(time / 3600.0); - double minutes = whole_minutes - hours * 60.0; - - time_buffers[j].hour = static_cast(hours); - time_buffers[j].minute = static_cast(minutes); - time_buffers[j].second = static_cast(seconds); - time_buffers[j].second_part = - static_cast(frac_seconds * 1000000.0); - time_buffers[j].neg = neg; + LOG_VERBOSE << time; + + bool neg = false; + if (time < 0) { + neg = true; + time = -time; + } + double whole_seconds = ::trunc(time); + double frac_seconds = time - whole_seconds; + double whole_minutes = ::trunc(time / 60.0); + double seconds = whole_seconds - whole_minutes * 60.0; + double hours = ::trunc(time / 3600.0); + double minutes = whole_minutes - hours * 60.0; + + time_buffers[j].hour = static_cast(hours); + time_buffers[j].minute = static_cast(minutes); + time_buffers[j].second = static_cast(seconds); + time_buffers[j].second_part = + static_cast(frac_seconds * 1000000.0); + time_buffers[j].neg = neg; } diff --git a/src/MariaBinding.h b/src/MariaBinding.h index b1322bc1..e66bd096 100644 --- a/src/MariaBinding.h +++ b/src/MariaBinding.h @@ -7,33 +7,33 @@ #include "MariaTypes.h" class MariaBinding : public boost::noncopyable { - MYSQL_STMT* statement; - List params; + MYSQL_STMT* statement; + List params; - int p; - R_xlen_t i, n_rows; - std::vector bindings; - boost::container::vector is_null; - std::vector types; - std::vector time_buffers; + int p; + R_xlen_t i, n_rows; + std::vector bindings; + boost::container::vector is_null; + std::vector types; + std::vector time_buffers; - public: - MariaBinding(); - ~MariaBinding(); +public: + MariaBinding(); + ~MariaBinding(); - public: - void setup(MYSQL_STMT* statement_); +public: + void setup(MYSQL_STMT* statement_); - void init_binding(const List& params); - bool bind_next_row(); + void init_binding(const List& params); + bool bind_next_row(); - private: - void binding_update(int j, enum_field_types type, int size); +private: + void binding_update(int j, enum_field_types type, int size); - void clear_date_buffer(int j); - void set_date_buffer(int j, int date); - void clear_time_buffer(int j); - void set_time_buffer(int j, double time); + void clear_date_buffer(int j); + void set_date_buffer(int j, int date); + void clear_time_buffer(int j); + void set_time_buffer(int j, double time); }; #endif diff --git a/src/MariaResult.cpp b/src/MariaResult.cpp index 1708e0f8..a25e20de 100644 --- a/src/MariaResult.cpp +++ b/src/MariaResult.cpp @@ -9,25 +9,25 @@ MariaResult::MariaResult(const DbConnectionPtr& pConn, const std::string& sql, bool is_statement) : DbResult(pConn) { - boost::scoped_ptr res( - new MariaResultPrep(pConn, is_statement)); - try { - res->send_query(sql); - } catch (const MariaResultPrep::UnsupportedPS& e) { - res.reset(NULL); - // is_statement info might be worthwhile to pass to simple queries as - // well - res.reset(new MariaResultSimple(pConn, is_statement)); - res->send_query(sql); - } + boost::scoped_ptr res( + new MariaResultPrep(pConn, is_statement)); + try { + res->send_query(sql); + } catch (const MariaResultPrep::UnsupportedPS& e) { + res.reset(NULL); + // is_statement info might be worthwhile to pass to simple queries as + // well + res.reset(new MariaResultSimple(pConn, is_statement)); + res->send_query(sql); + } - res.swap(impl); + res.swap(impl); } DbResult* MariaResult::create_and_send_query(const DbConnectionPtr& con, const std::string& sql, bool is_statement) { - return new MariaResult(con, sql, is_statement); + return new MariaResult(con, sql, is_statement); } // Publics ///////////////////////////////////////////////////////////////////// diff --git a/src/MariaResult.h b/src/MariaResult.h index 1586aa66..6835fe38 100644 --- a/src/MariaResult.h +++ b/src/MariaResult.h @@ -6,17 +6,17 @@ // MariaResult ----------------------------------------------------------------- class MariaResult : public DbResult { - protected: - MariaResult(const DbConnectionPtr& pConn, const std::string& sql, - bool is_statement); +protected: + MariaResult(const DbConnectionPtr& pConn, const std::string& sql, + bool is_statement); - public: - static DbResult* create_and_send_query(const DbConnectionPtr& con, - const std::string& sql, - bool is_statement); +public: + static DbResult* create_and_send_query(const DbConnectionPtr& con, + const std::string& sql, + bool is_statement); - public: - void close(); +public: + void close(); }; #endif // __RMARIADB_MARIA_RESULT__ diff --git a/src/MariaResultImpl.h b/src/MariaResultImpl.h index 7e592174..1bf2791c 100644 --- a/src/MariaResultImpl.h +++ b/src/MariaResultImpl.h @@ -2,23 +2,23 @@ #define RMARIADB_MARIARESULTIMPL_H class MariaResultImpl { - public: - MariaResultImpl(); - virtual ~MariaResultImpl(); +public: + MariaResultImpl(); + virtual ~MariaResultImpl(); - public: - virtual void send_query(const std::string& sql) = 0; - virtual void close() = 0; +public: + virtual void send_query(const std::string& sql) = 0; + virtual void close() = 0; - virtual void bind(const List& params) = 0; + virtual void bind(const List& params) = 0; - virtual List get_column_info() = 0; + virtual List get_column_info() = 0; - virtual List fetch(int n_max = -1) = 0; + virtual List fetch(int n_max = -1) = 0; - virtual int n_rows_affected() = 0; - virtual int n_rows_fetched() = 0; - virtual bool complete() const = 0; + virtual int n_rows_affected() = 0; + virtual int n_rows_fetched() = 0; + virtual bool complete() const = 0; }; #endif // RMARIADB_MARIARESULTIMPL_H diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index 95938a54..5c976835 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -18,248 +18,249 @@ MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, bound_(false), complete_(false), is_statement_(is_statement) { - pStatement_ = mysql_stmt_init(pConn_->get_conn()); - if (pStatement_ == NULL) - stop("Out of memory"); + pStatement_ = mysql_stmt_init(pConn_->get_conn()); + if (pStatement_ == NULL) + stop("Out of memory"); } MariaResultPrep::~MariaResultPrep() { - MariaResultPrep::close(); + MariaResultPrep::close(); } void MariaResultPrep::send_query(const std::string& sql) { - LOG_DEBUG << sql; + LOG_DEBUG << sql; - LOG_DEBUG << "mysql_stmt_prepare()"; - if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { - if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { - throw UnsupportedPS(); - } + LOG_DEBUG << "mysql_stmt_prepare()"; + if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { + if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { + throw UnsupportedPS(); + } - throw_error(); - } + throw_error(); + } - nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); - LOG_DEBUG << nParams_; + nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); + LOG_DEBUG << nParams_; - // Need to set pSpec_ before calling execute() - pSpec_ = mysql_stmt_result_metadata(pStatement_); + // Need to set pSpec_ before calling execute() + pSpec_ = mysql_stmt_result_metadata(pStatement_); - if (nParams_ == 0) { - // Not parameterised so we can execute immediately - execute(); - bound_ = true; - } + if (nParams_ == 0) { + // Not parameterised so we can execute immediately + execute(); + bound_ = true; + } - if (has_result()) { - // Query returns results, so cache column names and types - cache_metadata(); - bindingOutput_.setup(pStatement_, types_); - } + if (has_result()) { + // Query returns results, so cache column names and types + cache_metadata(); + bindingOutput_.setup(pStatement_, types_); + } } void MariaResultPrep::close() { - if (has_result()) { - mysql_free_result(pSpec_); - pSpec_ = NULL; - } + if (has_result()) { + mysql_free_result(pSpec_); + pSpec_ = NULL; + } - if (pStatement_ != NULL) { - mysql_stmt_close(pStatement_); - pStatement_ = NULL; - } + if (pStatement_ != NULL) { + mysql_stmt_close(pStatement_); + pStatement_ = NULL; + } - pConn_->autocommit(); + pConn_->autocommit(); } void MariaResultPrep::execute() { - LOG_VERBOSE; + LOG_VERBOSE; - complete_ = false; + complete_ = false; - LOG_DEBUG << "mysql_stmt_execute()"; - if (mysql_stmt_execute(pStatement_) != 0) { - LOG_VERBOSE; - throw_error(); - } - LOG_VERBOSE << "has_result()"; - if (!has_result() && !is_statement_) { - LOG_VERBOSE; - // try again after mysql_stmt_execute, in case pSpec_ == NULL - pSpec_ = mysql_stmt_result_metadata(pStatement_); - } - if (!has_result()) { - LOG_VERBOSE; - rowsAffected_ += mysql_stmt_affected_rows(pStatement_); - } + LOG_DEBUG << "mysql_stmt_execute()"; + if (mysql_stmt_execute(pStatement_) != 0) { + LOG_VERBOSE; + throw_error(); + } + LOG_VERBOSE << "has_result()"; + if (!has_result() && !is_statement_) { + LOG_VERBOSE; + // try again after mysql_stmt_execute, in case pSpec_ == NULL + pSpec_ = mysql_stmt_result_metadata(pStatement_); + } + if (!has_result()) { + LOG_VERBOSE; + rowsAffected_ += mysql_stmt_affected_rows(pStatement_); + } } void MariaResultPrep::bind(const List& params) { - rowsAffected_ = 0; + rowsAffected_ = 0; - bindingInput_.setup(pStatement_); - bindingInput_.init_binding(params); + bindingInput_.setup(pStatement_); + bindingInput_.init_binding(params); - if (has_result()) { - complete_ = true; - } else { - while (bindingInput_.bind_next_row()) { - execute(); + if (has_result()) { + complete_ = true; + } else { + while (bindingInput_.bind_next_row()) { + execute(); + } } - } - bound_ = true; + bound_ = true; } List MariaResultPrep::get_column_info() { - CharacterVector names(nCols_), types(nCols_); - for (int i = 0; i < nCols_; i++) { - names[i] = names_[i]; - types[i] = type_name(types_[i]); - } + CharacterVector names(nCols_), types(nCols_); + for (int i = 0; i < nCols_; i++) { + names[i] = names_[i]; + types[i] = type_name(types_[i]); + } - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } bool MariaResultPrep::has_result() const { - return pSpec_ != NULL; + return pSpec_ != NULL; } bool MariaResultPrep::step() { - LOG_VERBOSE; - - while (!fetch_row()) { LOG_VERBOSE; - if (!bindingInput_.bind_next_row()) - return false; - execute(); - } + while (!fetch_row()) { + LOG_VERBOSE; - rowsFetched_++; + if (!bindingInput_.bind_next_row()) + return false; + execute(); + } - LOG_VERBOSE << rowsFetched_; - return true; + rowsFetched_++; + + LOG_VERBOSE << rowsFetched_; + return true; } bool MariaResultPrep::fetch_row() { - LOG_VERBOSE; + LOG_VERBOSE; - if (complete_) - return false; + if (complete_) + return false; - LOG_VERBOSE << "mysql_stmt_fetch()"; - int result = mysql_stmt_fetch(pStatement_); + LOG_VERBOSE << "mysql_stmt_fetch()"; + int result = mysql_stmt_fetch(pStatement_); - LOG_VERBOSE << result; + LOG_VERBOSE << result; - switch (result) { - // We expect truncation whenever there's a string or blob - case MYSQL_DATA_TRUNCATED: - case 0: - return true; - case 1: - throw_error(); - case MYSQL_NO_DATA: - complete_ = true; + switch (result) { + // We expect truncation whenever there's a string or blob + case MYSQL_DATA_TRUNCATED: + case 0: + return true; + case 1: + throw_error(); + case MYSQL_NO_DATA: + complete_ = true; + return false; + } return false; - } - return false; } List MariaResultPrep::fetch(int n_max) { - if (!bound_) - stop("Query needs to be bound before fetching"); - if (!has_result()) { - if (names_.size() == 0) { - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and " - "also " - "avoid dbFetch()"); + if (!bound_) + stop("Query needs to be bound before fetching"); + if (!has_result()) { + if (names_.size() == 0) { + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and " + "also " + "avoid dbFetch()"); + } + return df_create(types_, names_, 0); } - return df_create(types_, names_, 0); - } - int n = (n_max < 0) ? 100 : n_max; - List out = df_create(types_, names_, n); - if (n == 0) - return out; + int n = (n_max < 0) ? 100 : n_max; + List out = df_create(types_, names_, n); + if (n == 0) + return out; - int i = 0; + int i = 0; - for (;;) { - if (i >= n && n_max > 0) - break; + for (;;) { + if (i >= n && n_max > 0) + break; - if (!step()) - break; + if (!step()) + break; - if (i >= n) { - n *= 2; - out = df_resize(out, n); - } + if (i >= n) { + n *= 2; + out = df_resize(out, n); + } - for (int j = 0; j < nCols_; ++j) { - // Rcout << i << "," << j << "\n"; - bindingOutput_.set_list_value(out[j], i, j); - } + for (int j = 0; j < nCols_; ++j) { + // Rcout << i << "," << j << "\n"; + bindingOutput_.set_list_value(out[j], i, j); + } - ++i; - if (i % 1024 == 0) - checkUserInterrupt(); - } + ++i; + if (i % 1024 == 0) + checkUserInterrupt(); + } - // Trim back to what we actually used - if (i < n) { - out = df_resize(out, i); - } - // Set up S3 classes - df_s3(out, types_); + // Trim back to what we actually used + if (i < n) { + out = df_resize(out, i); + } + // Set up S3 classes + df_s3(out, types_); - return out; + return out; } int MariaResultPrep::n_rows_affected() { - if (!bound_) - return NA_INTEGER; - // FIXME: > 2^32 rows? - return static_cast(rowsAffected_); + if (!bound_) + return NA_INTEGER; + // FIXME: > 2^32 rows? + return static_cast(rowsAffected_); } int MariaResultPrep::n_rows_fetched() { - if (!bound_) - return 0; - // FIXME: > 2^32 rows? - return static_cast(rowsFetched_); + if (!bound_) + return 0; + // FIXME: > 2^32 rows? + return static_cast(rowsFetched_); } bool MariaResultPrep::complete() const { - if (!bound_) - return FALSE; - return !has_result() || // query doesn't have results - complete_; // we've fetched all available results + if (!bound_) + return FALSE; + return !has_result() || // query doesn't have results + complete_; // we've fetched all available results } void MariaResultPrep::throw_error() { - stop("%s [%i]", mysql_stmt_error(pStatement_), mysql_stmt_errno(pStatement_)); + stop("%s [%i]", mysql_stmt_error(pStatement_), + mysql_stmt_errno(pStatement_)); } void MariaResultPrep::cache_metadata() { - LOG_VERBOSE; + LOG_VERBOSE; - nCols_ = mysql_num_fields(pSpec_); - MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); + nCols_ = mysql_num_fields(pSpec_); + MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); - for (int i = 0; i < nCols_; ++i) { - names_.push_back(fields[i].name); + for (int i = 0; i < nCols_; ++i) { + names_.push_back(fields[i].name); - bool binary = fields[i].charsetnr == 63; - bool length1 = fields[i].length == 1; - MariaFieldType type = - variable_type_from_field_type(fields[i].type, binary, length1); - types_.push_back(type); + bool binary = fields[i].charsetnr == 63; + bool length1 = fields[i].length == 1; + MariaFieldType type = + variable_type_from_field_type(fields[i].type, binary, length1); + types_.push_back(type); - LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type - << ", " << binary << ") => " << type_name(type); - } + LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type + << ", " << binary << ") => " << type_name(type); + } } diff --git a/src/MariaResultPrep.h b/src/MariaResultPrep.h index c1fe8cb3..f07ef302 100644 --- a/src/MariaResultPrep.h +++ b/src/MariaResultPrep.h @@ -14,52 +14,52 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultPrep : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - MYSQL_STMT* pStatement_; - MYSQL_RES* pSpec_; - uint64_t rowsAffected_, rowsFetched_; + MYSQL_STMT* pStatement_; + MYSQL_RES* pSpec_; + uint64_t rowsAffected_, rowsFetched_; - int nCols_, nParams_; - bool bound_, complete_; - bool is_statement_; + int nCols_, nParams_; + bool bound_, complete_; + bool is_statement_; - std::vector types_; - std::vector names_; - MariaBinding bindingInput_; - MariaRow bindingOutput_; + std::vector types_; + std::vector names_; + MariaBinding bindingInput_; + MariaRow bindingOutput_; - public: - MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); - ~MariaResultPrep(); +public: + MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); + ~MariaResultPrep(); - public: - virtual void send_query(const std::string& sql); - virtual void close(); +public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; - public: - class UnsupportedPS : public std::exception {}; +public: + class UnsupportedPS : public std::exception {}; - private: - void execute(); +private: + void execute(); - bool has_result() const; - bool step(); - bool fetch_row(); - void NORET throw_error(); + bool has_result() const; + bool step(); + bool fetch_row(); + void NORET throw_error(); - private: - void cache_metadata(); +private: + void cache_metadata(); }; #endif diff --git a/src/MariaResultSimple.cpp b/src/MariaResultSimple.cpp index 77c98b83..1ffaebc0 100644 --- a/src/MariaResultSimple.cpp +++ b/src/MariaResultSimple.cpp @@ -6,60 +6,60 @@ MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement) : pConn_(pConn) { - (void)is_statement; + (void)is_statement; } MariaResultSimple::~MariaResultSimple() { - MariaResultSimple::close(); + MariaResultSimple::close(); } void MariaResultSimple::send_query(const std::string& sql) { - LOG_DEBUG << sql; + LOG_DEBUG << sql; - exec(sql); + exec(sql); } void MariaResultSimple::close() { - LOG_VERBOSE; + LOG_VERBOSE; } void MariaResultSimple::bind(const List& /*params*/) { - LOG_VERBOSE; + LOG_VERBOSE; - stop( - "This query is not supported by the prepared statement protocol, no " - "parameters can be bound."); + stop( + "This query is not supported by the prepared statement protocol, no " + "parameters can be bound."); } List MariaResultSimple::get_column_info() { - CharacterVector names(0), types(0); + CharacterVector names(0), types(0); - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } List MariaResultSimple::fetch(int /*n_max*/) { - LOG_VERBOSE; - - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and also " - "avoid " - "dbFetch()"); - return df_create(std::vector(), std::vector(), - 0); + LOG_VERBOSE; + + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and also " + "avoid " + "dbFetch()"); + return df_create(std::vector(), std::vector(), + 0); } int MariaResultSimple::n_rows_affected() { - return 0; + return 0; } int MariaResultSimple::n_rows_fetched() { - return 0; + return 0; } bool MariaResultSimple::complete() const { - return true; + return true; } void MariaResultSimple::exec(const std::string& sql) { - pConn_->exec(sql); + pConn_->exec(sql); } diff --git a/src/MariaResultSimple.h b/src/MariaResultSimple.h index 242cfe69..9cf0f846 100644 --- a/src/MariaResultSimple.h +++ b/src/MariaResultSimple.h @@ -14,28 +14,28 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultSimple : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - public: - MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); - ~MariaResultSimple(); +public: + MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); + ~MariaResultSimple(); - public: - virtual void send_query(const std::string& sql); - virtual void close(); +public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; - private: - void exec(const std::string& sql); +private: + void exec(const std::string& sql); }; #endif diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index be0f3f03..998b6752 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -13,245 +13,245 @@ MariaRow::~MariaRow() { void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& types) { - LOG_VERBOSE; - - pStatement_ = pStatement; - types_ = types; - n_ = static_cast(types_.size()); - - bindings_.resize(n_); - buffers_.resize(n_); - lengths_.resize(n_); - nulls_.resize(n_); - errors_.resize(n_); - - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types_[j]); - - // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html - switch (types_[j]) { - case MY_INT32: - bindings_[j].buffer_type = MYSQL_TYPE_LONG; - buffers_[j].resize(4); - break; - case MY_INT64: - bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; - buffers_[j].resize(8); - break; - case MY_DBL: - bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; - buffers_[j].resize(8); - break; - case MY_DATE: - bindings_[j].buffer_type = MYSQL_TYPE_DATE; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_TIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_STR: - bindings_[j].buffer_type = MYSQL_TYPE_STRING; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_RAW: - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_LGL: - // BIT(1) is bound to logical, in absence of dedicated type - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(4); - break; + LOG_VERBOSE; + + pStatement_ = pStatement; + types_ = types; + n_ = static_cast(types_.size()); + + bindings_.resize(n_); + buffers_.resize(n_); + lengths_.resize(n_); + nulls_.resize(n_); + errors_.resize(n_); + + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types_[j]); + + // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html + switch (types_[j]) { + case MY_INT32: + bindings_[j].buffer_type = MYSQL_TYPE_LONG; + buffers_[j].resize(4); + break; + case MY_INT64: + bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; + buffers_[j].resize(8); + break; + case MY_DBL: + bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; + buffers_[j].resize(8); + break; + case MY_DATE: + bindings_[j].buffer_type = MYSQL_TYPE_DATE; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_TIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_STR: + bindings_[j].buffer_type = MYSQL_TYPE_STRING; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_RAW: + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_LGL: + // BIT(1) is bound to logical, in absence of dedicated type + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(4); + break; + } + + lengths_[j] = buffers_[j].size(); + bindings_[j].buffer_length = buffers_[j].size(); + if (bindings_[j].buffer_length > 0) + bindings_[j].buffer = &buffers_[j][0]; + else + bindings_[j].buffer = NULL; + bindings_[j].length = &lengths_[j]; + bindings_[j].is_null = &nulls_[j]; + bindings_[j].is_unsigned = true; + bindings_[j].error = &errors_[j]; + + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; } - lengths_[j] = buffers_[j].size(); - bindings_[j].buffer_length = buffers_[j].size(); - if (bindings_[j].buffer_length > 0) - bindings_[j].buffer = &buffers_[j][0]; - else - bindings_[j].buffer = NULL; - bindings_[j].length = &lengths_[j]; - bindings_[j].is_null = &nulls_[j]; - bindings_[j].is_unsigned = true; - bindings_[j].error = &errors_[j]; - - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; - } - - LOG_DEBUG << "mysql_stmt_bind_result()"; - if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { - stop("Error binding result: %s", mysql_stmt_error(pStatement)); - } + LOG_DEBUG << "mysql_stmt_bind_result()"; + if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { + stop("Error binding result: %s", mysql_stmt_error(pStatement)); + } - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; - } + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; + } } bool MariaRow::is_null(int j) { - return nulls_[j] == 1; + return nulls_[j] == 1; } int MariaRow::value_bool(int j) { - if (is_null(j)) { - return NA_LOGICAL; - } else { - return static_cast(value_int(j) == 1); - } + if (is_null(j)) { + return NA_LOGICAL; + } else { + return static_cast(value_int(j) == 1); + } } int MariaRow::value_int(int j) { - return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); } int64_t MariaRow::value_int64(int j) { - return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); } double MariaRow::value_double(int j) { - return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); + return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); } SEXP MariaRow::value_string(int j) { - if (is_null(j)) - return NA_STRING; + if (is_null(j)) + return NA_STRING; - fetch_buffer(j); - int len = static_cast(buffers_[j].size()); - if (len == 0) - return R_BlankString; + fetch_buffer(j); + int len = static_cast(buffers_[j].size()); + if (len == 0) + return R_BlankString; - const char* val = reinterpret_cast(&buffers_[j][0]); - return Rf_mkCharLenCE(val, len, CE_UTF8); + const char* val = reinterpret_cast(&buffers_[j][0]); + return Rf_mkCharLenCE(val, len, CE_UTF8); } SEXP MariaRow::value_raw(int j) { - if (is_null(j)) - return R_NilValue; + if (is_null(j)) + return R_NilValue; - fetch_buffer(j); - SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); - memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); + fetch_buffer(j); + SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); + memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); - return bytes; + return bytes; } double MariaRow::value_date_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days) * 86400.0 + - static_cast(mytime->hour) * (60.0 * 60) + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; - LOG_VERBOSE << date_time; - return date_time; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days) * 86400.0 + + static_cast(mytime->hour) * (60.0 * 60) + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_date(int j) { - if (is_null(j)) - return NA_REAL; + if (is_null(j)) + return NA_REAL; - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days); - LOG_VERBOSE << date_time; - return date_time; + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days); + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - return static_cast(mytime->hour) * 3600.0 + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + return static_cast(mytime->hour) * 3600.0 + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; } void MariaRow::set_list_value(SEXP x, int i, int j) { - switch (types_[j]) { - case MY_INT32: - INTEGER(x)[i] = value_int(j); - break; - case MY_INT64: - INTEGER64(x)[i] = value_int64(j); - break; - case MY_DBL: - REAL(x)[i] = value_double(j); - break; - case MY_DATE: - REAL(x)[i] = value_date(j); - break; - case MY_DATE_TIME: - REAL(x)[i] = value_date_time(j); - break; - case MY_TIME: - REAL(x)[i] = value_time(j); - break; - case MY_STR: - SET_STRING_ELT(x, i, value_string(j)); - break; - case MY_RAW: - SET_VECTOR_ELT(x, i, value_raw(j)); - break; - case MY_LGL: - LOGICAL(x)[i] = value_bool(j); - break; - } + switch (types_[j]) { + case MY_INT32: + INTEGER(x)[i] = value_int(j); + break; + case MY_INT64: + INTEGER64(x)[i] = value_int64(j); + break; + case MY_DBL: + REAL(x)[i] = value_double(j); + break; + case MY_DATE: + REAL(x)[i] = value_date(j); + break; + case MY_DATE_TIME: + REAL(x)[i] = value_date_time(j); + break; + case MY_TIME: + REAL(x)[i] = value_time(j); + break; + case MY_STR: + SET_STRING_ELT(x, i, value_string(j)); + break; + case MY_RAW: + SET_VECTOR_ELT(x, i, value_raw(j)); + break; + case MY_LGL: + LOGICAL(x)[i] = value_bool(j); + break; + } } void MariaRow::fetch_buffer(int j) { - unsigned long length = lengths_[j]; - LOG_VERBOSE << length; + unsigned long length = lengths_[j]; + LOG_VERBOSE << length; - buffers_[j].resize(length); - if (length == 0) - return; + buffers_[j].resize(length); + if (length == 0) + return; - bindings_[j].buffer = &buffers_[j][0]; // might have moved - bindings_[j].buffer_length = length; + bindings_[j].buffer = &buffers_[j][0]; // might have moved + bindings_[j].buffer_length = length; - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; - LOG_DEBUG << "mysql_stmt_fetch_column()"; - int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); - LOG_VERBOSE << result; + LOG_DEBUG << "mysql_stmt_fetch_column()"; + int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); + LOG_VERBOSE << result; - if (result != 0) - stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); + if (result != 0) + stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); - // Reset buffer length to zero for next row - bindings_[j].buffer = NULL; - bindings_[j].buffer_length = 0; + // Reset buffer length to zero for next row + bindings_[j].buffer = NULL; + bindings_[j].buffer_length = 0; } diff --git a/src/MariaRow.h b/src/MariaRow.h index 45efd3b5..553edd02 100644 --- a/src/MariaRow.h +++ b/src/MariaRow.h @@ -8,40 +8,41 @@ #include "MariaTypes.h" class MariaRow : public boost::noncopyable { - MYSQL_STMT* pStatement_; - - int n_; - std::vector bindings_; - - std::vector types_; - std::vector > buffers_; - std::vector lengths_; - boost::container::vector nulls_, errors_; - - public: - MariaRow(); - ~MariaRow(); - - public: - void setup(MYSQL_STMT* pStatement, const std::vector& types); - void set_list_value(SEXP x, int i, int j); - - private: - // Value accessors - // ----------------------------------------------------------- - bool is_null(int j); - - int value_int(int j); - int value_bool(int j); - int64_t value_int64(int j); - double value_double(int j); - SEXP value_string(int j); - SEXP value_raw(int j); - double value_date_time(int j); - double value_date(int j); - double value_time(int j); - - void fetch_buffer(int j); + MYSQL_STMT* pStatement_; + + int n_; + std::vector bindings_; + + std::vector types_; + std::vector > buffers_; + std::vector lengths_; + boost::container::vector nulls_, errors_; + +public: + MariaRow(); + ~MariaRow(); + +public: + void setup(MYSQL_STMT* pStatement, + const std::vector& types); + void set_list_value(SEXP x, int i, int j); + +private: + // Value accessors + // ----------------------------------------------------------- + bool is_null(int j); + + int value_int(int j); + int value_bool(int j); + int64_t value_int64(int j); + double value_double(int j); + SEXP value_string(int j); + SEXP value_raw(int j); + double value_date_time(int j); + double value_date(int j); + double value_time(int j); + + void fetch_buffer(int j); }; #endif diff --git a/src/MariaTypes.cpp b/src/MariaTypes.cpp index cfecffba..746b5f09 100644 --- a/src/MariaTypes.cpp +++ b/src/MariaTypes.cpp @@ -7,157 +7,157 @@ bool all_raw(SEXP x); MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, bool length1) { - switch (type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_YEAR: - return MY_INT32; + switch (type) { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_YEAR: + return MY_INT32; - case MYSQL_TYPE_LONGLONG: - return MY_INT64; + case MYSQL_TYPE_LONGLONG: + return MY_INT64; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - return MY_DBL; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - return MY_DATE_TIME; - case MYSQL_TYPE_DATE: - return MY_DATE; - case MYSQL_TYPE_TIME: - return MY_TIME; - case MYSQL_TYPE_BIT: - if (length1) { - return MY_LGL; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + return MY_DBL; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_NEWDATE: + return MY_DATE_TIME; + case MYSQL_TYPE_DATE: + return MY_DATE; + case MYSQL_TYPE_TIME: + return MY_TIME; + case MYSQL_TYPE_BIT: + if (length1) { + return MY_LGL; + } + // fallthrough + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_SET: + return MY_STR; + case MYSQL_TYPE_GEOMETRY: + return MY_RAW; + case MYSQL_TYPE_NULL: + return MY_INT32; + default: + throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); } - // fallthrough - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_SET: - return MY_STR; - case MYSQL_TYPE_GEOMETRY: - return MY_RAW; - case MYSQL_TYPE_NULL: - return MY_INT32; - default: - throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); - } } std::string type_name(MariaFieldType type) { - switch (type) { - case MY_INT32: - return "integer"; - case MY_INT64: - return "integer64"; - case MY_DBL: - return "double"; - case MY_STR: - return "string"; - case MY_DATE: - return "Date"; - case MY_DATE_TIME: - return "POSIXct"; - case MY_TIME: - return "hms"; - case MY_RAW: - return "raw"; - case MY_LGL: - return "logical"; - } - throw std::runtime_error("Invalid typeName"); + switch (type) { + case MY_INT32: + return "integer"; + case MY_INT64: + return "integer64"; + case MY_DBL: + return "double"; + case MY_STR: + return "string"; + case MY_DATE: + return "Date"; + case MY_DATE_TIME: + return "POSIXct"; + case MY_TIME: + return "hms"; + case MY_RAW: + return "raw"; + case MY_LGL: + return "logical"; + } + throw std::runtime_error("Invalid typeName"); } SEXPTYPE type_sexp(MariaFieldType type) { - switch (type) { - case MY_INT32: - return INTSXP; - case MY_INT64: - return INT64SXP; - case MY_DBL: - return REALSXP; - case MY_STR: - return STRSXP; - case MY_DATE: - return REALSXP; - case MY_DATE_TIME: - return REALSXP; - case MY_TIME: - return REALSXP; - case MY_RAW: - return VECSXP; - case MY_LGL: - return LGLSXP; - } - throw std::runtime_error("Invalid typeSEXP"); + switch (type) { + case MY_INT32: + return INTSXP; + case MY_INT64: + return INT64SXP; + case MY_DBL: + return REALSXP; + case MY_STR: + return STRSXP; + case MY_DATE: + return REALSXP; + case MY_DATE_TIME: + return REALSXP; + case MY_TIME: + return REALSXP; + case MY_RAW: + return VECSXP; + case MY_LGL: + return LGLSXP; + } + throw std::runtime_error("Invalid typeSEXP"); } std::string r_class(RObject x) { - RObject klass_(x.attr("class")); - std::string klass; - if (klass_ == R_NilValue) - return ""; + RObject klass_(x.attr("class")); + std::string klass; + if (klass_ == R_NilValue) + return ""; - CharacterVector klassv = as(klass_); - return std::string(klassv[klassv.length() - 1]); + CharacterVector klassv = as(klass_); + return std::string(klassv[klassv.length() - 1]); } MariaFieldType variable_type_from_object(const RObject& type) { - std::string klass = r_class(type); + std::string klass = r_class(type); - switch (TYPEOF(type)) { - case LGLSXP: - return MY_LGL; - case INTSXP: - return MY_INT32; - case REALSXP: - if (klass == "Date") - return MY_DATE; - if (klass == "POSIXt") - return MY_DATE_TIME; - if (klass == "difftime") - return MY_TIME; - if (klass == "integer64") - return MY_INT64; - return MY_DBL; - case STRSXP: - return MY_STR; - case VECSXP: - if (klass == "blob") - return MY_RAW; - if (all_raw(type)) - return MY_RAW; - break; - } + switch (TYPEOF(type)) { + case LGLSXP: + return MY_LGL; + case INTSXP: + return MY_INT32; + case REALSXP: + if (klass == "Date") + return MY_DATE; + if (klass == "POSIXt") + return MY_DATE_TIME; + if (klass == "difftime") + return MY_TIME; + if (klass == "integer64") + return MY_INT64; + return MY_DBL; + case STRSXP: + return MY_STR; + case VECSXP: + if (klass == "blob") + return MY_RAW; + if (all_raw(type)) + return MY_RAW; + break; + } - stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); - return MY_STR; + stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); + return MY_STR; } bool all_raw(SEXP x) { - List xx(x); - for (R_xlen_t i = 0; i < xx.length(); ++i) { - switch (TYPEOF(xx[i])) { - case RAWSXP: - case NILSXP: - break; + List xx(x); + for (R_xlen_t i = 0; i < xx.length(); ++i) { + switch (TYPEOF(xx[i])) { + case RAWSXP: + case NILSXP: + break; - default: - return false; + default: + return false; + } } - } - return true; + return true; } diff --git a/src/MariaTypes.h b/src/MariaTypes.h index df681f7f..8d3fd866 100644 --- a/src/MariaTypes.h +++ b/src/MariaTypes.h @@ -2,15 +2,15 @@ #define __RMARIADB_MARIA_TYPES__ enum MariaFieldType { - MY_INT32, - MY_INT64, // output only - MY_DBL, - MY_STR, - MY_DATE, - MY_DATE_TIME, - MY_TIME, - MY_RAW, - MY_LGL // for BIT(1) + MY_INT32, + MY_INT64, // output only + MY_DBL, + MY_STR, + MY_DATE, + MY_DATE_TIME, + MY_TIME, + MY_RAW, + MY_LGL // for BIT(1) }; MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index d772fcae..0aae55fc 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -29,270 +29,271 @@ RcppExport SEXP _RMariaDB_connection_create( SEXP default_fileSEXP, SEXP ssl_keySEXP, SEXP ssl_certSEXP, SEXP ssl_caSEXP, SEXP ssl_capathSEXP, SEXP ssl_cipherSEXP, SEXP timeoutSEXP, SEXP reconnectSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter&>::type host( - hostSEXP); - Rcpp::traits::input_parameter&>::type user( - userSEXP); - Rcpp::traits::input_parameter&>::type password( - passwordSEXP); - Rcpp::traits::input_parameter&>::type db(dbSEXP); - Rcpp::traits::input_parameter::type port(portSEXP); - Rcpp::traits::input_parameter&>::type unix_socket( - unix_socketSEXP); - Rcpp::traits::input_parameter::type client_flag( - client_flagSEXP); - Rcpp::traits::input_parameter&>::type groups( - groupsSEXP); - Rcpp::traits::input_parameter&>::type - default_file(default_fileSEXP); - Rcpp::traits::input_parameter&>::type ssl_key( - ssl_keySEXP); - Rcpp::traits::input_parameter&>::type ssl_cert( - ssl_certSEXP); - Rcpp::traits::input_parameter&>::type ssl_ca( - ssl_caSEXP); - Rcpp::traits::input_parameter&>::type ssl_capath( - ssl_capathSEXP); - Rcpp::traits::input_parameter&>::type ssl_cipher( - ssl_cipherSEXP); - Rcpp::traits::input_parameter::type timeout(timeoutSEXP); - Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); - rcpp_result_gen = Rcpp::wrap( - connection_create(host, user, password, db, port, unix_socket, - client_flag, groups, default_file, ssl_key, ssl_cert, - ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter&>::type host( + hostSEXP); + Rcpp::traits::input_parameter&>::type user( + userSEXP); + Rcpp::traits::input_parameter&>::type password( + passwordSEXP); + Rcpp::traits::input_parameter&>::type db( + dbSEXP); + Rcpp::traits::input_parameter::type port(portSEXP); + Rcpp::traits::input_parameter&>::type + unix_socket(unix_socketSEXP); + Rcpp::traits::input_parameter::type client_flag( + client_flagSEXP); + Rcpp::traits::input_parameter&>::type groups( + groupsSEXP); + Rcpp::traits::input_parameter&>::type + default_file(default_fileSEXP); + Rcpp::traits::input_parameter&>::type ssl_key( + ssl_keySEXP); + Rcpp::traits::input_parameter&>::type ssl_cert( + ssl_certSEXP); + Rcpp::traits::input_parameter&>::type ssl_ca( + ssl_caSEXP); + Rcpp::traits::input_parameter&>::type + ssl_capath(ssl_capathSEXP); + Rcpp::traits::input_parameter&>::type + ssl_cipher(ssl_cipherSEXP); + Rcpp::traits::input_parameter::type timeout(timeoutSEXP); + Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); + rcpp_result_gen = Rcpp::wrap( + connection_create(host, user, password, db, port, unix_socket, + client_flag, groups, default_file, ssl_key, ssl_cert, + ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); + return rcpp_result_gen; + END_RCPP } // connection_valid bool connection_valid(XPtr con_); RcppExport SEXP _RMariaDB_connection_valid(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); + return rcpp_result_gen; + END_RCPP } // connection_release void connection_release(XPtr con_); RcppExport SEXP _RMariaDB_connection_release(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - connection_release(con_); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + connection_release(con_); + return R_NilValue; + END_RCPP } // connection_info List connection_info(DbConnection* con); RcppExport SEXP _RMariaDB_connection_info(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_info(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_info(con)); + return rcpp_result_gen; + END_RCPP } // connection_quote_string CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs); RcppExport SEXP _RMariaDB_connection_quote_string(SEXP conSEXP, SEXP xsSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - Rcpp::traits::input_parameter::type xs(xsSEXP); - rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + Rcpp::traits::input_parameter::type xs(xsSEXP); + rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); + return rcpp_result_gen; + END_RCPP } // connection_begin_transaction void connection_begin_transaction(XPtr con); RcppExport SEXP _RMariaDB_connection_begin_transaction(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_begin_transaction(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_begin_transaction(con); + return R_NilValue; + END_RCPP } // connection_commit void connection_commit(XPtr con); RcppExport SEXP _RMariaDB_connection_commit(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_commit(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_commit(con); + return R_NilValue; + END_RCPP } // connection_rollback void connection_rollback(XPtr con); RcppExport SEXP _RMariaDB_connection_rollback(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_rollback(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_rollback(con); + return R_NilValue; + END_RCPP } // connection_is_transacting bool connection_is_transacting(DbConnection* con); RcppExport SEXP _RMariaDB_connection_is_transacting(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); + return rcpp_result_gen; + END_RCPP } // driver_init void driver_init(); RcppExport SEXP _RMariaDB_driver_init() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_init(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_init(); + return R_NilValue; + END_RCPP } // driver_done void driver_done(); RcppExport SEXP _RMariaDB_driver_done() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_done(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_done(); + return R_NilValue; + END_RCPP } // version IntegerVector version(); RcppExport SEXP _RMariaDB_version() { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - rcpp_result_gen = Rcpp::wrap(version()); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = Rcpp::wrap(version()); + return rcpp_result_gen; + END_RCPP } // init_logging void init_logging(const std::string& log_level); RcppExport SEXP _RMariaDB_init_logging(SEXP log_levelSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type log_level( - log_levelSEXP); - init_logging(log_level); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type log_level( + log_levelSEXP); + init_logging(log_level); + return R_NilValue; + END_RCPP } // result_create XPtr result_create(XPtr con, std::string sql, bool is_statement); RcppExport SEXP _RMariaDB_result_create(SEXP conSEXP, SEXP sqlSEXP, SEXP is_statementSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - Rcpp::traits::input_parameter::type sql(sqlSEXP); - Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); - rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + Rcpp::traits::input_parameter::type sql(sqlSEXP); + Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); + rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); + return rcpp_result_gen; + END_RCPP } // result_release void result_release(XPtr res); RcppExport SEXP _RMariaDB_result_release(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res(resSEXP); - result_release(res); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res(resSEXP); + result_release(res); + return R_NilValue; + END_RCPP } // result_valid bool result_valid(XPtr res_); RcppExport SEXP _RMariaDB_result_valid(SEXP res_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res_(res_SEXP); - rcpp_result_gen = Rcpp::wrap(result_valid(res_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res_(res_SEXP); + rcpp_result_gen = Rcpp::wrap(result_valid(res_)); + return rcpp_result_gen; + END_RCPP } // result_fetch List result_fetch(DbResult* res, const int n); RcppExport SEXP _RMariaDB_result_fetch(SEXP resSEXP, SEXP nSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type n(nSEXP); - rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type n(nSEXP); + rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); + return rcpp_result_gen; + END_RCPP } // result_bind void result_bind(DbResult* res, List params); RcppExport SEXP _RMariaDB_result_bind(SEXP resSEXP, SEXP paramsSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type params(paramsSEXP); - result_bind(res, params); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type params(paramsSEXP); + result_bind(res, params); + return R_NilValue; + END_RCPP } // result_has_completed bool result_has_completed(DbResult* res); RcppExport SEXP _RMariaDB_result_has_completed(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_fetched int result_rows_fetched(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_fetched(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_affected int result_rows_affected(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_affected(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); + return rcpp_result_gen; + END_RCPP } // result_column_info List result_column_info(DbResult* res); RcppExport SEXP _RMariaDB_result_column_info(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_column_info(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_column_info(res)); + return rcpp_result_gen; + END_RCPP } static const R_CallMethodDef CallEntries[] = { @@ -328,6 +329,6 @@ static const R_CallMethodDef CallEntries[] = { {NULL, NULL, 0}}; RcppExport void R_init_RMariaDB(DllInfo* dll) { - R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); - R_useDynamicSymbols(dll, FALSE); + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); } diff --git a/src/connection.cpp b/src/connection.cpp index 6f1ac842..7a8d17af 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -12,81 +12,81 @@ XPtr connection_create( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; + LOG_VERBOSE; - DbConnection* pConnPtr = new DbConnection; - try { - pConnPtr->connect(host, user, password, db, port, unix_socket, client_flag, - groups, default_file, ssl_key, ssl_cert, ssl_ca, - ssl_capath, ssl_cipher, timeout, reconnect); - } catch (...) { - delete pConnPtr; - throw; - } + DbConnection* pConnPtr = new DbConnection; + try { + pConnPtr->connect(host, user, password, db, port, unix_socket, + client_flag, groups, default_file, ssl_key, ssl_cert, + ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect); + } catch (...) { + delete pConnPtr; + throw; + } - DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); + DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); - return XPtr(pConn, true); + return XPtr(pConn, true); } // [[Rcpp::export]] bool connection_valid(XPtr con_) { - DbConnectionPtr* con = con_.get(); - return con && con->get()->is_valid(); + DbConnectionPtr* con = con_.get(); + return con && con->get()->is_valid(); } // [[Rcpp::export]] void connection_release(XPtr con_) { - if (!connection_valid(con_)) { - warning("Already disconnected"); - return; - } - - DbConnectionPtr* con = con_.get(); - con->get()->disconnect(); - con_.release(); + if (!connection_valid(con_)) { + warning("Already disconnected"); + return; + } + + DbConnectionPtr* con = con_.get(); + con->get()->disconnect(); + con_.release(); } // [[Rcpp::export]] List connection_info(DbConnection* con) { - return con->info(); + return con->info(); } // Quoting // [[Rcpp::export]] CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs) { - R_xlen_t n = xs.size(); - CharacterVector output(n); + R_xlen_t n = xs.size(); + CharacterVector output(n); - for (R_xlen_t i = 0; i < n; ++i) { - String x = xs[i]; - output[i] = con->quote_string(x); - } + for (R_xlen_t i = 0; i < n; ++i) { + String x = xs[i]; + output[i] = con->quote_string(x); + } - return output; + return output; } // Transactions // [[Rcpp::export]] void connection_begin_transaction(XPtr con) { - (*con)->begin_transaction(); + (*con)->begin_transaction(); } // [[Rcpp::export]] void connection_commit(XPtr con) { - (*con)->commit(); + (*con)->commit(); } // [[Rcpp::export]] void connection_rollback(XPtr con) { - (*con)->rollback(); + (*con)->rollback(); } // [[Rcpp::export]] bool connection_is_transacting(DbConnection* con) { - return con->is_transacting(); + return con->is_transacting(); } // Specific functions @@ -97,10 +97,10 @@ namespace Rcpp { template <> DbConnection* as(SEXP x) { - DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); - if (!connection) - stop("Invalid connection"); - return connection->get(); + DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); + if (!connection) + stop("Invalid connection"); + return connection->get(); } } // namespace Rcpp diff --git a/src/driver.cpp b/src/driver.cpp index aa940f86..5c05fbbe 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -10,22 +10,22 @@ // [[Rcpp::export]] void driver_init() { - mysql_library_init(0, NULL, NULL); + mysql_library_init(0, NULL, NULL); } // [[Rcpp::export]] void driver_done() { - mysql_library_end(); + mysql_library_end(); } // [[Rcpp::export]] IntegerVector version() { - return IntegerVector::create( - _[SERVER_VERSION] = MYSQL_VERSION_ID, - _[mysql_get_client_info()] = mysql_get_client_version()); + return IntegerVector::create( + _[SERVER_VERSION] = MYSQL_VERSION_ID, + _[mysql_get_client_info()] = mysql_get_client_version()); } // [[Rcpp::export]] void init_logging(const std::string& log_level) { - plog::init_r(log_level); + plog::init_r(log_level); } diff --git a/src/integer64.h b/src/integer64.h index 2f3b934c..2b0a6f42 100644 --- a/src/integer64.h +++ b/src/integer64.h @@ -6,7 +6,7 @@ #define NA_INTEGER64 (static_cast(0x8000000000000000)) inline int64_t* INTEGER64(SEXP x) { - return reinterpret_cast(REAL(x)); + return reinterpret_cast(REAL(x)); } #endif // RMARIADB_INTEGER64_H diff --git a/src/result.cpp b/src/result.cpp index 16a8aa4a..38a448fa 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -5,60 +5,60 @@ // [[Rcpp::export]] XPtr result_create(XPtr con, std::string sql, bool is_statement = false) { - (*con)->check_connection(); - DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); - return XPtr(res, true); + (*con)->check_connection(); + DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); + return XPtr(res, true); } // [[Rcpp::export]] void result_release(XPtr res) { - res.release(); + res.release(); } // [[Rcpp::export]] bool result_valid(XPtr res_) { - DbResult* res = res_.get(); - return res != NULL && res->is_active(); + DbResult* res = res_.get(); + return res != NULL && res->is_active(); } // [[Rcpp::export]] List result_fetch(DbResult* res, const int n) { - return res->fetch(n); + return res->fetch(n); } // [[Rcpp::export]] void result_bind(DbResult* res, List params) { - res->bind(params); + res->bind(params); } // [[Rcpp::export]] bool result_has_completed(DbResult* res) { - return res->complete(); + return res->complete(); } // [[Rcpp::export]] int result_rows_fetched(DbResult* res) { - return res->n_rows_fetched(); + return res->n_rows_fetched(); } // [[Rcpp::export]] int result_rows_affected(DbResult* res) { - return res->n_rows_affected(); + return res->n_rows_affected(); } // [[Rcpp::export]] List result_column_info(DbResult* res) { - return res->get_column_info(); + return res->get_column_info(); } namespace Rcpp { template <> DbResult* as(SEXP x) { - DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); - if (!result) - stop("Invalid result set"); - return result; + DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); + if (!result) + stop("Invalid result set"); + return result; } } // namespace Rcpp From 77eb101ec995aa6ebc6b6df51f751c42e569233e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 28 Nov 2022 14:39:44 +0100 Subject: [PATCH 8/9] No tabs, 2 spaces --- .clang-format | 6 +- src/DbConnection.cpp | 269 ++++++++++++----------- src/DbConnection.h | 90 ++++---- src/DbResult.cpp | 73 +++---- src/DbResult.h | 36 +-- src/MariaBinding.cpp | 450 +++++++++++++++++++------------------- src/MariaBinding.h | 42 ++-- src/MariaResult.cpp | 26 +-- src/MariaResult.h | 18 +- src/MariaResultImpl.h | 24 +- src/MariaResultPrep.cpp | 371 ++++++++++++++++--------------- src/MariaResultPrep.h | 66 +++--- src/MariaResultSimple.cpp | 46 ++-- src/MariaResultSimple.h | 30 +-- src/MariaRow.cpp | 386 ++++++++++++++++---------------- src/MariaRow.h | 69 +++--- src/MariaTypes.cpp | 264 +++++++++++----------- src/MariaTypes.h | 18 +- src/RcppExports.cpp | 361 +++++++++++++++--------------- src/connection.cpp | 76 +++---- src/driver.cpp | 12 +- src/integer64.h | 2 +- src/result.cpp | 32 +-- 23 files changed, 1381 insertions(+), 1386 deletions(-) diff --git a/.clang-format b/.clang-format index 8dd36a13..3b33b163 100644 --- a/.clang-format +++ b/.clang-format @@ -1,8 +1,8 @@ BasedOnStyle: Google Language: Cpp -TabWidth: 4 -IndentWidth: 4 -UseTab: ForIndentation +TabWidth: 8 +IndentWidth: 2 +UseTab: Never IndentCaseLabels: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index d02ffe58..b228c2c5 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -5,16 +5,16 @@ DbConnection::DbConnection() : pConn_(NULL), pCurrentResult_(NULL), transacting_(false) { - LOG_VERBOSE; + LOG_VERBOSE; } DbConnection::~DbConnection() { - LOG_VERBOSE; + LOG_VERBOSE; - if (is_valid()) { - warning("call dbDisconnect() when finished working with a connection"); - disconnect(); - } + if (is_valid()) { + warning("call dbDisconnect() when finished working with a connection"); + disconnect(); + } } void DbConnection::connect( @@ -27,201 +27,200 @@ void DbConnection::connect( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; - - this->pConn_ = mysql_init(NULL); - // Enable LOCAL INFILE for fast data ingest - unsigned int local_infile = 1; - mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); - // Default to UTF-8 - mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); - if (!groups.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, - as(groups).c_str()); - if (!default_file.isNull()) - mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, - as(default_file).c_str()); - - if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || - !ssl_capath.isNull() || !ssl_cipher.isNull()) { - mysql_ssl_set( - this->pConn_, - ssl_key.isNull() ? NULL : as(ssl_key).c_str(), - ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), - ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), - ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), - ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); - } - if (timeout > 0) { - mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); - } - if (reconnect) { - my_bool reconnect_ = 1; - mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); - } - - LOG_VERBOSE; - - if (!mysql_real_connect( - this->pConn_, host.isNull() ? NULL : as(host).c_str(), - user.isNull() ? NULL : as(user).c_str(), - password.isNull() ? NULL : as(password).c_str(), - db.isNull() ? NULL : as(db).c_str(), port, - unix_socket.isNull() ? NULL : as(unix_socket).c_str(), - client_flag)) { - std::string error = mysql_error(this->pConn_); - mysql_close(this->pConn_); - this->pConn_ = NULL; - - stop("Failed to connect: %s", error.c_str()); - } + LOG_VERBOSE; + + this->pConn_ = mysql_init(NULL); + // Enable LOCAL INFILE for fast data ingest + unsigned int local_infile = 1; + mysql_options(this->pConn_, MYSQL_OPT_LOCAL_INFILE, &local_infile); + // Default to UTF-8 + mysql_options(this->pConn_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); + if (!groups.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_GROUP, + as(groups).c_str()); + if (!default_file.isNull()) + mysql_options(this->pConn_, MYSQL_READ_DEFAULT_FILE, + as(default_file).c_str()); + + if (!ssl_key.isNull() || !ssl_cert.isNull() || !ssl_ca.isNull() || + !ssl_capath.isNull() || !ssl_cipher.isNull()) { + mysql_ssl_set( + this->pConn_, + ssl_key.isNull() ? NULL : as(ssl_key).c_str(), + ssl_cert.isNull() ? NULL : as(ssl_cert).c_str(), + ssl_ca.isNull() ? NULL : as(ssl_ca).c_str(), + ssl_capath.isNull() ? NULL : as(ssl_capath).c_str(), + ssl_cipher.isNull() ? NULL : as(ssl_cipher).c_str()); + } + if (timeout > 0) { + mysql_options(this->pConn_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); + } + if (reconnect) { + my_bool reconnect_ = 1; + mysql_options(this->pConn_, MYSQL_OPT_RECONNECT, (void*)&reconnect_); + } + + LOG_VERBOSE; + + if (!mysql_real_connect( + this->pConn_, host.isNull() ? NULL : as(host).c_str(), + user.isNull() ? NULL : as(user).c_str(), + password.isNull() ? NULL : as(password).c_str(), + db.isNull() ? NULL : as(db).c_str(), port, + unix_socket.isNull() ? NULL : as(unix_socket).c_str(), + client_flag)) { + std::string error = mysql_error(this->pConn_); + mysql_close(this->pConn_); + this->pConn_ = NULL; + + stop("Failed to connect: %s", error.c_str()); + } } void DbConnection::disconnect() { - if (!is_valid()) - return; + if (!is_valid()) + return; - if (has_query()) { - warning( - "%s\n%s", "There is a result object still in use.", - "The connection will be automatically released when it is closed"); - } + if (has_query()) { + warning("%s\n%s", "There is a result object still in use.", + "The connection will be automatically released when it is closed"); + } - try { - mysql_close(get_conn()); - } catch (...) { - }; + try { + mysql_close(get_conn()); + } catch (...) { + }; - pConn_ = NULL; + pConn_ = NULL; } bool DbConnection::is_valid() { - return !!get_conn(); + return !!get_conn(); } void DbConnection::check_connection() { - if (!is_valid()) { - stop("Invalid or closed connection"); - } + if (!is_valid()) { + stop("Invalid or closed connection"); + } } List DbConnection::info() { - return List::create( - _["host"] = std::string(pConn_->host), - _["username"] = std::string(pConn_->user), - _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), - _["con.type"] = std::string(mysql_get_host_info(pConn_)), - _["db.version"] = std::string(mysql_get_server_info(pConn_)), - _["port"] = NA_INTEGER, - _["protocol.version"] = (int)mysql_get_proto_info(pConn_), - _["thread.id"] = (int)mysql_thread_id(pConn_)); + return List::create( + _["host"] = std::string(pConn_->host), + _["username"] = std::string(pConn_->user), + _["dbname"] = std::string(pConn_->db ? pConn_->db : ""), + _["con.type"] = std::string(mysql_get_host_info(pConn_)), + _["db.version"] = std::string(mysql_get_server_info(pConn_)), + _["port"] = NA_INTEGER, + _["protocol.version"] = (int)mysql_get_proto_info(pConn_), + _["thread.id"] = (int)mysql_thread_id(pConn_)); } MYSQL* DbConnection::get_conn() { - return pConn_; + return pConn_; } SEXP DbConnection::quote_string(const String& input) { - if (input == NA_STRING) - return get_null_string(); + if (input == NA_STRING) + return get_null_string(); - const char* input_cstr = input.get_cstring(); - size_t input_len = strlen(input_cstr); + const char* input_cstr = input.get_cstring(); + size_t input_len = strlen(input_cstr); - // Create buffer with enough room to escape every character - std::string output = "'"; - output.resize(input_len * 2 + 3); + // Create buffer with enough room to escape every character + std::string output = "'"; + output.resize(input_len * 2 + 3); - size_t end = - mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); + size_t end = + mysql_real_escape_string(pConn_, &output[1], input_cstr, input_len); - output.resize(end + 1); - output.append("'"); - return Rf_mkCharCE(output.c_str(), CE_UTF8); + output.resize(end + 1); + output.append("'"); + return Rf_mkCharCE(output.c_str(), CE_UTF8); } SEXP DbConnection::get_null_string() { - static RObject null = Rf_mkCharCE("NULL", CE_UTF8); - return null; + static RObject null = Rf_mkCharCE("NULL", CE_UTF8); + return null; } void DbConnection::set_current_result(DbResult* pResult) { - if (pResult == pCurrentResult_) - return; + if (pResult == pCurrentResult_) + return; - if (pCurrentResult_ != NULL) { - if (pResult != NULL) - warning("Cancelling previous query"); + if (pCurrentResult_ != NULL) { + if (pResult != NULL) + warning("Cancelling previous query"); - pCurrentResult_->close(); - } - pCurrentResult_ = pResult; + pCurrentResult_->close(); + } + pCurrentResult_ = pResult; } void DbConnection::reset_current_result(DbResult* pResult) { - // FIXME: What to do if not current result is reset? - if (pResult != pCurrentResult_) - return; + // FIXME: What to do if not current result is reset? + if (pResult != pCurrentResult_) + return; - pCurrentResult_->close(); - pCurrentResult_ = NULL; + pCurrentResult_->close(); + pCurrentResult_ = NULL; } bool DbConnection::is_current_result(const DbResult* pResult) const { - return pCurrentResult_ == pResult; + return pCurrentResult_ == pResult; } bool DbConnection::has_query() { - return pCurrentResult_ != NULL; + return pCurrentResult_ != NULL; } bool DbConnection::exec(const std::string& sql) { - check_connection(); + check_connection(); - if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) - stop("Error executing query: %s", mysql_error(pConn_)); + if (mysql_real_query(pConn_, sql.data(), sql.size()) != 0) + stop("Error executing query: %s", mysql_error(pConn_)); - MYSQL_RES* res = mysql_store_result(pConn_); - if (res != NULL) - mysql_free_result(res); + MYSQL_RES* res = mysql_store_result(pConn_); + if (res != NULL) + mysql_free_result(res); - autocommit(); + autocommit(); - return true; + return true; } void DbConnection::begin_transaction() { - if (is_transacting()) - stop("Nested transactions not supported."); - check_connection(); + if (is_transacting()) + stop("Nested transactions not supported."); + check_connection(); - transacting_ = true; + transacting_ = true; } void DbConnection::commit() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_commit(get_conn()); - transacting_ = false; + mysql_commit(get_conn()); + transacting_ = false; } void DbConnection::rollback() { - if (!is_transacting()) - stop("Call dbBegin() to start a transaction."); - check_connection(); + if (!is_transacting()) + stop("Call dbBegin() to start a transaction."); + check_connection(); - mysql_rollback(get_conn()); - transacting_ = false; + mysql_rollback(get_conn()); + transacting_ = false; } bool DbConnection::is_transacting() const { - return transacting_; + return transacting_; } void DbConnection::autocommit() { - if (!is_transacting() && get_conn()) { - mysql_commit(get_conn()); - } + if (!is_transacting() && get_conn()) { + mysql_commit(get_conn()); + } } diff --git a/src/DbConnection.h b/src/DbConnection.h index e9179e94..c166a857 100644 --- a/src/DbConnection.h +++ b/src/DbConnection.h @@ -11,51 +11,51 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class DbConnection : boost::noncopyable { - MYSQL* pConn_; - DbResult* pCurrentResult_; - bool transacting_; - -public: - DbConnection(); - ~DbConnection(); - -public: - void connect(const Nullable& host, - const Nullable& user, - const Nullable& password, - const Nullable& db, unsigned int port, - const Nullable& unix_socket, - unsigned long client_flag, const Nullable& groups, - const Nullable& default_file, - const Nullable& ssl_key, - const Nullable& ssl_cert, - const Nullable& ssl_ca, - const Nullable& ssl_capath, - const Nullable& ssl_cipher, int timeout, - bool reconnect); - void disconnect(); - bool is_valid(); - void check_connection(); - - List info(); - MYSQL* get_conn(); - - SEXP quote_string(const String& input); - static SEXP get_null_string(); - - // Cancels previous query, if needed. - void set_current_result(DbResult* pResult); - void reset_current_result(DbResult* pResult); - bool is_current_result(const DbResult* pResult) const; - bool has_query(); - - bool exec(const std::string& sql); - - void begin_transaction(); - void commit(); - void rollback(); - bool is_transacting() const; - void autocommit(); + MYSQL* pConn_; + DbResult* pCurrentResult_; + bool transacting_; + + public: + DbConnection(); + ~DbConnection(); + + public: + void connect(const Nullable& host, + const Nullable& user, + const Nullable& password, + const Nullable& db, unsigned int port, + const Nullable& unix_socket, + unsigned long client_flag, const Nullable& groups, + const Nullable& default_file, + const Nullable& ssl_key, + const Nullable& ssl_cert, + const Nullable& ssl_ca, + const Nullable& ssl_capath, + const Nullable& ssl_cipher, int timeout, + bool reconnect); + void disconnect(); + bool is_valid(); + void check_connection(); + + List info(); + MYSQL* get_conn(); + + SEXP quote_string(const String& input); + static SEXP get_null_string(); + + // Cancels previous query, if needed. + void set_current_result(DbResult* pResult); + void reset_current_result(DbResult* pResult); + bool is_current_result(const DbResult* pResult) const; + bool has_query(); + + bool exec(const std::string& sql); + + void begin_transaction(); + void commit(); + void rollback(); + bool is_transacting() const; + void autocommit(); }; #endif diff --git a/src/DbResult.cpp b/src/DbResult.cpp index 440c111a..a6e5a23c 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -7,79 +7,78 @@ // Construction //////////////////////////////////////////////////////////////// DbResult::DbResult(const DbConnectionPtr& pConn) : pConn_(pConn) { - pConn_->check_connection(); + pConn_->check_connection(); - // subclass constructor can throw, the destructor will remove the - // current result set - pConn_->set_current_result(this); + // subclass constructor can throw, the destructor will remove the + // current result set + pConn_->set_current_result(this); } DbResult::~DbResult() { - try { - if (is_active()) { - pConn_->reset_current_result(this); - } - } catch (...) { - } + try { + if (is_active()) { + pConn_->reset_current_result(this); + } + } catch (...) { + } } // Publics ///////////////////////////////////////////////////////////////////// bool DbResult::complete() const { - return (impl == NULL) || impl->complete(); + return (impl == NULL) || impl->complete(); } bool DbResult::is_active() const { - return pConn_->is_current_result(this); + return pConn_->is_current_result(this); } int DbResult::n_rows_fetched() { - return impl->n_rows_fetched(); + return impl->n_rows_fetched(); } int DbResult::n_rows_affected() { - return impl->n_rows_affected(); + return impl->n_rows_affected(); } void DbResult::bind(const List& params) { - validate_params(params); - impl->bind(params); + validate_params(params); + impl->bind(params); } List DbResult::fetch(const int n_max) { - if (!is_active()) - stop("Inactive result set"); + if (!is_active()) + stop("Inactive result set"); - return impl->fetch(n_max); + return impl->fetch(n_max); } List DbResult::get_column_info() { - List out = impl->get_column_info(); + List out = impl->get_column_info(); - out.attr("row.names") = - IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); - out.attr("class") = "data.frame"; + out.attr("row.names") = IntegerVector::create(NA_INTEGER, -Rf_length(out[0])); + out.attr("class") = "data.frame"; - return out; + return out; } void DbResult::close() { - // Called from destructor - if (impl) - impl->close(); + // Called from destructor + if (impl) + impl->close(); } // Privates /////////////////////////////////////////////////////////////////// void DbResult::validate_params(const List& params) const { - if (params.size() != 0) { - SEXP first_col = params[0]; - int n = Rf_length(first_col); - - for (int j = 1; j < params.size(); ++j) { - SEXP col = params[j]; - if (Rf_length(col) != n) - stop("Parameter %i does not have length %d.", j + 1, n); - } - } + if (params.size() != 0) { + SEXP first_col = params[0]; + int n = Rf_length(first_col); + + for (int j = 1; j < params.size(); ++j) { + SEXP col = params[j]; + if (Rf_length(col) != n) + stop("Parameter %i does not have length %d.", j + 1, n); + } + } } diff --git a/src/DbResult.h b/src/DbResult.h index 96fb8ecb..625e54e7 100644 --- a/src/DbResult.h +++ b/src/DbResult.h @@ -13,32 +13,32 @@ typedef boost::shared_ptr DbConnectionPtr; // DbResult -------------------------------------------------------------------- class DbResult : boost::noncopyable { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; -protected: - boost::scoped_ptr impl; + protected: + boost::scoped_ptr impl; -protected: - DbResult(const DbConnectionPtr& pConn); + protected: + DbResult(const DbConnectionPtr& pConn); -public: - ~DbResult(); + public: + ~DbResult(); -public: - void close(); + public: + void close(); - bool complete() const; - bool is_active() const; - int n_rows_fetched(); - int n_rows_affected(); + bool complete() const; + bool is_active() const; + int n_rows_fetched(); + int n_rows_affected(); - void bind(const List& params); - List fetch(int n_max = -1); + void bind(const List& params); + List fetch(int n_max = -1); - List get_column_info(); + List get_column_info(); -private: - void validate_params(const List& params) const; + private: + void validate_params(const List& params) const; }; #endif // __RDBI_DB_RESULT__ diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index 7ebf3703..a7006b2f 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -12,253 +12,253 @@ MariaBinding::~MariaBinding() { } void MariaBinding::setup(MYSQL_STMT* statement_) { - LOG_VERBOSE; + LOG_VERBOSE; - statement = statement_; - p = static_cast(mysql_stmt_param_count(statement)); + statement = statement_; + p = static_cast(mysql_stmt_param_count(statement)); - bindings.resize(p); - types.resize(p); - is_null.resize(p); - time_buffers.resize(p); + bindings.resize(p); + types.resize(p); + is_null.resize(p); + time_buffers.resize(p); } void MariaBinding::init_binding(const List& params_) { - LOG_VERBOSE; - - params = params_; - - if (params.size() == 0) { - stop("Query has no parameters"); - } - - if (p != params.size()) { - stop("Number of params don't match (%i vs %i)", p, params.size()); - } - - i = 0; - - for (int j = 0; j < p; ++j) { - RObject param(params[j]); - MariaFieldType type = variable_type_from_object(param); - types[j] = type; - - LOG_VERBOSE << j << " -> " << type_name(type); - - if (j == 0) { - n_rows = Rf_xlength(param); - } - - switch (type) { - case MY_LGL: - binding_update(j, MYSQL_TYPE_TINY, 1); - break; - case MY_INT32: - binding_update(j, MYSQL_TYPE_LONG, 4); - break; - case MY_DBL: - binding_update(j, MYSQL_TYPE_DOUBLE, 8); - break; - case MY_DATE: - binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); - break; - case MY_TIME: - binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); - break; - case MY_STR: - binding_update(j, MYSQL_TYPE_STRING, 0); - break; - case MY_RAW: - binding_update(j, MYSQL_TYPE_BLOB, 0); - break; - case MY_INT64: - binding_update(j, MYSQL_TYPE_LONGLONG, 0); - break; - } - } + LOG_VERBOSE; + + params = params_; + + if (params.size() == 0) { + stop("Query has no parameters"); + } + + if (p != params.size()) { + stop("Number of params don't match (%i vs %i)", p, params.size()); + } + + i = 0; + + for (int j = 0; j < p; ++j) { + RObject param(params[j]); + MariaFieldType type = variable_type_from_object(param); + types[j] = type; + + LOG_VERBOSE << j << " -> " << type_name(type); + + if (j == 0) { + n_rows = Rf_xlength(param); + } + + switch (type) { + case MY_LGL: + binding_update(j, MYSQL_TYPE_TINY, 1); + break; + case MY_INT32: + binding_update(j, MYSQL_TYPE_LONG, 4); + break; + case MY_DBL: + binding_update(j, MYSQL_TYPE_DOUBLE, 8); + break; + case MY_DATE: + binding_update(j, MYSQL_TYPE_DATE, sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + binding_update(j, MYSQL_TYPE_DATETIME, sizeof(MYSQL_TIME)); + break; + case MY_TIME: + binding_update(j, MYSQL_TYPE_TIME, sizeof(MYSQL_TIME)); + break; + case MY_STR: + binding_update(j, MYSQL_TYPE_STRING, 0); + break; + case MY_RAW: + binding_update(j, MYSQL_TYPE_BLOB, 0); + break; + case MY_INT64: + binding_update(j, MYSQL_TYPE_LONGLONG, 0); + break; + } + } } bool MariaBinding::bind_next_row() { - LOG_VERBOSE; - - if (i >= n_rows) - return false; - - for (int j = 0; j < p; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types[j]); - - bool missing = false; - RObject col(params[j]); - - switch (types[j]) { - case MY_LGL: - if (LOGICAL(col)[i] == NA_LOGICAL) { - missing = true; - break; - } - bindings[j].buffer = &LOGICAL(col)[i]; - break; - case MY_INT32: - if (INTEGER(col)[i] == NA_INTEGER) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER(col)[i]; - break; - case MY_DBL: - if (ISNA(REAL(col)[i])) { - missing = true; - break; - } - bindings[j].buffer = &REAL(col)[i]; - break; - case MY_STR: - if (STRING_ELT(col, i) == NA_STRING) { - missing = true; - break; - } else { - SEXP string = STRING_ELT(col, i); - bindings[j].buffer = const_cast(CHAR(string)); - bindings[j].buffer_length = Rf_length(string); - } - break; - case MY_RAW: { - SEXP raw = VECTOR_ELT(col, i); - if (Rf_isNull(raw)) { - missing = true; - } else { - bindings[j].buffer_length = Rf_length(raw); - bindings[j].buffer = RAW(raw); - } - break; - } - case MY_DATE: - case MY_DATE_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - } else { - double val = REAL(col)[i]; - LOG_VERBOSE << val; - if (types[j] == MY_DATE) { - set_date_buffer(j, static_cast(::floor(val))); - clear_time_buffer(j); - } else { - double days = ::floor(val / 86400.0); - set_date_buffer(j, static_cast(days)); - set_time_buffer(j, val - days * 86400.0); - } - LOG_VERBOSE; - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_TIME: - if (ISNAN(REAL(col)[i])) { - missing = true; - break; - } else { - double val = REAL(col)[i]; - clear_date_buffer(j); - set_time_buffer(j, val); - bindings[j].buffer_length = sizeof(MYSQL_TIME); - bindings[j].buffer = &time_buffers[j]; - } - break; - case MY_INT64: - if (INTEGER64(col)[i] == NA_INTEGER64) { - missing = true; - break; - } - bindings[j].buffer = &INTEGER64(col)[i]; - break; - } - is_null[j] = missing; - } - - LOG_DEBUG << "Binding"; - mysql_stmt_bind_param(statement, &bindings[0]); - - LOG_DEBUG << "Done binding row " << i; - i++; - return true; + LOG_VERBOSE; + + if (i >= n_rows) + return false; + + for (int j = 0; j < p; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types[j]); + + bool missing = false; + RObject col(params[j]); + + switch (types[j]) { + case MY_LGL: + if (LOGICAL(col)[i] == NA_LOGICAL) { + missing = true; + break; + } + bindings[j].buffer = &LOGICAL(col)[i]; + break; + case MY_INT32: + if (INTEGER(col)[i] == NA_INTEGER) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER(col)[i]; + break; + case MY_DBL: + if (ISNA(REAL(col)[i])) { + missing = true; + break; + } + bindings[j].buffer = &REAL(col)[i]; + break; + case MY_STR: + if (STRING_ELT(col, i) == NA_STRING) { + missing = true; + break; + } else { + SEXP string = STRING_ELT(col, i); + bindings[j].buffer = const_cast(CHAR(string)); + bindings[j].buffer_length = Rf_length(string); + } + break; + case MY_RAW: { + SEXP raw = VECTOR_ELT(col, i); + if (Rf_isNull(raw)) { + missing = true; + } else { + bindings[j].buffer_length = Rf_length(raw); + bindings[j].buffer = RAW(raw); + } + break; + } + case MY_DATE: + case MY_DATE_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + } else { + double val = REAL(col)[i]; + LOG_VERBOSE << val; + if (types[j] == MY_DATE) { + set_date_buffer(j, static_cast(::floor(val))); + clear_time_buffer(j); + } else { + double days = ::floor(val / 86400.0); + set_date_buffer(j, static_cast(days)); + set_time_buffer(j, val - days * 86400.0); + } + LOG_VERBOSE; + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_TIME: + if (ISNAN(REAL(col)[i])) { + missing = true; + break; + } else { + double val = REAL(col)[i]; + clear_date_buffer(j); + set_time_buffer(j, val); + bindings[j].buffer_length = sizeof(MYSQL_TIME); + bindings[j].buffer = &time_buffers[j]; + } + break; + case MY_INT64: + if (INTEGER64(col)[i] == NA_INTEGER64) { + missing = true; + break; + } + bindings[j].buffer = &INTEGER64(col)[i]; + break; + } + is_null[j] = missing; + } + + LOG_DEBUG << "Binding"; + mysql_stmt_bind_param(statement, &bindings[0]); + + LOG_DEBUG << "Done binding row " << i; + i++; + return true; } void MariaBinding::binding_update(int j, enum_field_types type, int size) { - LOG_VERBOSE << j << ", " << type << ", " << size; + LOG_VERBOSE << j << ", " << type << ", " << size; - bindings[j].buffer_length = size; - bindings[j].buffer_type = type; - bindings[j].is_null = &is_null[j]; + bindings[j].buffer_length = size; + bindings[j].buffer_type = type; + bindings[j].is_null = &is_null[j]; } void MariaBinding::clear_date_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].year = 0; - time_buffers[j].month = 0; - time_buffers[j].day = 0; + LOG_VERBOSE << j; + time_buffers[j].year = 0; + time_buffers[j].month = 0; + time_buffers[j].day = 0; } void MariaBinding::set_date_buffer(int j, const int date) { - LOG_VERBOSE << date; - - // https://howardhinnant.github.io/date_algorithms.html#civil_from_days - const int date_0 = date + 719468; - const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; - const unsigned doe = - static_cast(date_0 - era * 146097); // [0, 146096] - LOG_VERBOSE << doe; - const unsigned yoe = - (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] - LOG_VERBOSE << yoe; - const int y = static_cast(yoe) + era * 400; - const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] - const unsigned mp = (5 * doy + 2) / 153; // [0, 11] - const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] - const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] - const unsigned yr = y + (m <= 2); - - // gmtime() fails for dates < 1970 on Windows - LOG_VERBOSE << date_0; - LOG_VERBOSE << yr; - LOG_VERBOSE << m; - LOG_VERBOSE << d; - - time_buffers[j].year = yr; - time_buffers[j].month = m; - time_buffers[j].day = d; + LOG_VERBOSE << date; + + // https://howardhinnant.github.io/date_algorithms.html#civil_from_days + const int date_0 = date + 719468; + const int era = (date_0 >= 0 ? date_0 : date_0 - 146096) / 146097; + const unsigned doe = + static_cast(date_0 - era * 146097); // [0, 146096] + LOG_VERBOSE << doe; + const unsigned yoe = + (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] + LOG_VERBOSE << yoe; + const int y = static_cast(yoe) + era * 400; + const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] + const unsigned mp = (5 * doy + 2) / 153; // [0, 11] + const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] + const unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] + const unsigned yr = y + (m <= 2); + + // gmtime() fails for dates < 1970 on Windows + LOG_VERBOSE << date_0; + LOG_VERBOSE << yr; + LOG_VERBOSE << m; + LOG_VERBOSE << d; + + time_buffers[j].year = yr; + time_buffers[j].month = m; + time_buffers[j].day = d; } void MariaBinding::clear_time_buffer(int j) { - LOG_VERBOSE << j; - time_buffers[j].hour = 0; - time_buffers[j].minute = 0; - time_buffers[j].second = 0; - time_buffers[j].second_part = 0; - time_buffers[j].neg = 0; + LOG_VERBOSE << j; + time_buffers[j].hour = 0; + time_buffers[j].minute = 0; + time_buffers[j].second = 0; + time_buffers[j].second_part = 0; + time_buffers[j].neg = 0; } void MariaBinding::set_time_buffer(int j, double time) { - LOG_VERBOSE << time; - - bool neg = false; - if (time < 0) { - neg = true; - time = -time; - } - double whole_seconds = ::trunc(time); - double frac_seconds = time - whole_seconds; - double whole_minutes = ::trunc(time / 60.0); - double seconds = whole_seconds - whole_minutes * 60.0; - double hours = ::trunc(time / 3600.0); - double minutes = whole_minutes - hours * 60.0; - - time_buffers[j].hour = static_cast(hours); - time_buffers[j].minute = static_cast(minutes); - time_buffers[j].second = static_cast(seconds); - time_buffers[j].second_part = - static_cast(frac_seconds * 1000000.0); - time_buffers[j].neg = neg; + LOG_VERBOSE << time; + + bool neg = false; + if (time < 0) { + neg = true; + time = -time; + } + double whole_seconds = ::trunc(time); + double frac_seconds = time - whole_seconds; + double whole_minutes = ::trunc(time / 60.0); + double seconds = whole_seconds - whole_minutes * 60.0; + double hours = ::trunc(time / 3600.0); + double minutes = whole_minutes - hours * 60.0; + + time_buffers[j].hour = static_cast(hours); + time_buffers[j].minute = static_cast(minutes); + time_buffers[j].second = static_cast(seconds); + time_buffers[j].second_part = + static_cast(frac_seconds * 1000000.0); + time_buffers[j].neg = neg; } diff --git a/src/MariaBinding.h b/src/MariaBinding.h index e66bd096..b1322bc1 100644 --- a/src/MariaBinding.h +++ b/src/MariaBinding.h @@ -7,33 +7,33 @@ #include "MariaTypes.h" class MariaBinding : public boost::noncopyable { - MYSQL_STMT* statement; - List params; + MYSQL_STMT* statement; + List params; - int p; - R_xlen_t i, n_rows; - std::vector bindings; - boost::container::vector is_null; - std::vector types; - std::vector time_buffers; + int p; + R_xlen_t i, n_rows; + std::vector bindings; + boost::container::vector is_null; + std::vector types; + std::vector time_buffers; -public: - MariaBinding(); - ~MariaBinding(); + public: + MariaBinding(); + ~MariaBinding(); -public: - void setup(MYSQL_STMT* statement_); + public: + void setup(MYSQL_STMT* statement_); - void init_binding(const List& params); - bool bind_next_row(); + void init_binding(const List& params); + bool bind_next_row(); -private: - void binding_update(int j, enum_field_types type, int size); + private: + void binding_update(int j, enum_field_types type, int size); - void clear_date_buffer(int j); - void set_date_buffer(int j, int date); - void clear_time_buffer(int j); - void set_time_buffer(int j, double time); + void clear_date_buffer(int j); + void set_date_buffer(int j, int date); + void clear_time_buffer(int j); + void set_time_buffer(int j, double time); }; #endif diff --git a/src/MariaResult.cpp b/src/MariaResult.cpp index a25e20de..3ff33974 100644 --- a/src/MariaResult.cpp +++ b/src/MariaResult.cpp @@ -9,25 +9,25 @@ MariaResult::MariaResult(const DbConnectionPtr& pConn, const std::string& sql, bool is_statement) : DbResult(pConn) { - boost::scoped_ptr res( - new MariaResultPrep(pConn, is_statement)); - try { - res->send_query(sql); - } catch (const MariaResultPrep::UnsupportedPS& e) { - res.reset(NULL); - // is_statement info might be worthwhile to pass to simple queries as - // well - res.reset(new MariaResultSimple(pConn, is_statement)); - res->send_query(sql); - } + boost::scoped_ptr res( + new MariaResultPrep(pConn, is_statement)); + try { + res->send_query(sql); + } catch (const MariaResultPrep::UnsupportedPS& e) { + res.reset(NULL); + // is_statement info might be worthwhile to pass to simple queries as + // well + res.reset(new MariaResultSimple(pConn, is_statement)); + res->send_query(sql); + } - res.swap(impl); + res.swap(impl); } DbResult* MariaResult::create_and_send_query(const DbConnectionPtr& con, const std::string& sql, bool is_statement) { - return new MariaResult(con, sql, is_statement); + return new MariaResult(con, sql, is_statement); } // Publics ///////////////////////////////////////////////////////////////////// diff --git a/src/MariaResult.h b/src/MariaResult.h index 6835fe38..1586aa66 100644 --- a/src/MariaResult.h +++ b/src/MariaResult.h @@ -6,17 +6,17 @@ // MariaResult ----------------------------------------------------------------- class MariaResult : public DbResult { -protected: - MariaResult(const DbConnectionPtr& pConn, const std::string& sql, - bool is_statement); + protected: + MariaResult(const DbConnectionPtr& pConn, const std::string& sql, + bool is_statement); -public: - static DbResult* create_and_send_query(const DbConnectionPtr& con, - const std::string& sql, - bool is_statement); + public: + static DbResult* create_and_send_query(const DbConnectionPtr& con, + const std::string& sql, + bool is_statement); -public: - void close(); + public: + void close(); }; #endif // __RMARIADB_MARIA_RESULT__ diff --git a/src/MariaResultImpl.h b/src/MariaResultImpl.h index 1bf2791c..7e592174 100644 --- a/src/MariaResultImpl.h +++ b/src/MariaResultImpl.h @@ -2,23 +2,23 @@ #define RMARIADB_MARIARESULTIMPL_H class MariaResultImpl { -public: - MariaResultImpl(); - virtual ~MariaResultImpl(); + public: + MariaResultImpl(); + virtual ~MariaResultImpl(); -public: - virtual void send_query(const std::string& sql) = 0; - virtual void close() = 0; + public: + virtual void send_query(const std::string& sql) = 0; + virtual void close() = 0; - virtual void bind(const List& params) = 0; + virtual void bind(const List& params) = 0; - virtual List get_column_info() = 0; + virtual List get_column_info() = 0; - virtual List fetch(int n_max = -1) = 0; + virtual List fetch(int n_max = -1) = 0; - virtual int n_rows_affected() = 0; - virtual int n_rows_fetched() = 0; - virtual bool complete() const = 0; + virtual int n_rows_affected() = 0; + virtual int n_rows_fetched() = 0; + virtual bool complete() const = 0; }; #endif // RMARIADB_MARIARESULTIMPL_H diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index 5c976835..5e2434f9 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -18,249 +18,248 @@ MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, bound_(false), complete_(false), is_statement_(is_statement) { - pStatement_ = mysql_stmt_init(pConn_->get_conn()); - if (pStatement_ == NULL) - stop("Out of memory"); + pStatement_ = mysql_stmt_init(pConn_->get_conn()); + if (pStatement_ == NULL) + stop("Out of memory"); } MariaResultPrep::~MariaResultPrep() { - MariaResultPrep::close(); + MariaResultPrep::close(); } void MariaResultPrep::send_query(const std::string& sql) { - LOG_DEBUG << sql; - - LOG_DEBUG << "mysql_stmt_prepare()"; - if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { - if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { - throw UnsupportedPS(); - } - - throw_error(); - } - - nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); - LOG_DEBUG << nParams_; - - // Need to set pSpec_ before calling execute() - pSpec_ = mysql_stmt_result_metadata(pStatement_); - - if (nParams_ == 0) { - // Not parameterised so we can execute immediately - execute(); - bound_ = true; - } - - if (has_result()) { - // Query returns results, so cache column names and types - cache_metadata(); - bindingOutput_.setup(pStatement_, types_); - } + LOG_DEBUG << sql; + + LOG_DEBUG << "mysql_stmt_prepare()"; + if (mysql_stmt_prepare(pStatement_, sql.data(), sql.size()) != 0) { + if (mysql_stmt_errno(pStatement_) == ER_UNSUPPORTED_PS) { + throw UnsupportedPS(); + } + + throw_error(); + } + + nParams_ = static_cast(mysql_stmt_param_count(pStatement_)); + LOG_DEBUG << nParams_; + + // Need to set pSpec_ before calling execute() + pSpec_ = mysql_stmt_result_metadata(pStatement_); + + if (nParams_ == 0) { + // Not parameterised so we can execute immediately + execute(); + bound_ = true; + } + + if (has_result()) { + // Query returns results, so cache column names and types + cache_metadata(); + bindingOutput_.setup(pStatement_, types_); + } } void MariaResultPrep::close() { - if (has_result()) { - mysql_free_result(pSpec_); - pSpec_ = NULL; - } + if (has_result()) { + mysql_free_result(pSpec_); + pSpec_ = NULL; + } - if (pStatement_ != NULL) { - mysql_stmt_close(pStatement_); - pStatement_ = NULL; - } + if (pStatement_ != NULL) { + mysql_stmt_close(pStatement_); + pStatement_ = NULL; + } - pConn_->autocommit(); + pConn_->autocommit(); } void MariaResultPrep::execute() { - LOG_VERBOSE; - - complete_ = false; - - LOG_DEBUG << "mysql_stmt_execute()"; - if (mysql_stmt_execute(pStatement_) != 0) { - LOG_VERBOSE; - throw_error(); - } - LOG_VERBOSE << "has_result()"; - if (!has_result() && !is_statement_) { - LOG_VERBOSE; - // try again after mysql_stmt_execute, in case pSpec_ == NULL - pSpec_ = mysql_stmt_result_metadata(pStatement_); - } - if (!has_result()) { - LOG_VERBOSE; - rowsAffected_ += mysql_stmt_affected_rows(pStatement_); - } + LOG_VERBOSE; + + complete_ = false; + + LOG_DEBUG << "mysql_stmt_execute()"; + if (mysql_stmt_execute(pStatement_) != 0) { + LOG_VERBOSE; + throw_error(); + } + LOG_VERBOSE << "has_result()"; + if (!has_result() && !is_statement_) { + LOG_VERBOSE; + // try again after mysql_stmt_execute, in case pSpec_ == NULL + pSpec_ = mysql_stmt_result_metadata(pStatement_); + } + if (!has_result()) { + LOG_VERBOSE; + rowsAffected_ += mysql_stmt_affected_rows(pStatement_); + } } void MariaResultPrep::bind(const List& params) { - rowsAffected_ = 0; + rowsAffected_ = 0; - bindingInput_.setup(pStatement_); - bindingInput_.init_binding(params); + bindingInput_.setup(pStatement_); + bindingInput_.init_binding(params); - if (has_result()) { - complete_ = true; - } else { - while (bindingInput_.bind_next_row()) { - execute(); - } - } + if (has_result()) { + complete_ = true; + } else { + while (bindingInput_.bind_next_row()) { + execute(); + } + } - bound_ = true; + bound_ = true; } List MariaResultPrep::get_column_info() { - CharacterVector names(nCols_), types(nCols_); - for (int i = 0; i < nCols_; i++) { - names[i] = names_[i]; - types[i] = type_name(types_[i]); - } + CharacterVector names(nCols_), types(nCols_); + for (int i = 0; i < nCols_; i++) { + names[i] = names_[i]; + types[i] = type_name(types_[i]); + } - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } bool MariaResultPrep::has_result() const { - return pSpec_ != NULL; + return pSpec_ != NULL; } bool MariaResultPrep::step() { - LOG_VERBOSE; + LOG_VERBOSE; - while (!fetch_row()) { - LOG_VERBOSE; + while (!fetch_row()) { + LOG_VERBOSE; - if (!bindingInput_.bind_next_row()) - return false; - execute(); - } + if (!bindingInput_.bind_next_row()) + return false; + execute(); + } - rowsFetched_++; + rowsFetched_++; - LOG_VERBOSE << rowsFetched_; - return true; + LOG_VERBOSE << rowsFetched_; + return true; } bool MariaResultPrep::fetch_row() { - LOG_VERBOSE; - - if (complete_) - return false; - - LOG_VERBOSE << "mysql_stmt_fetch()"; - int result = mysql_stmt_fetch(pStatement_); - - LOG_VERBOSE << result; - - switch (result) { - // We expect truncation whenever there's a string or blob - case MYSQL_DATA_TRUNCATED: - case 0: - return true; - case 1: - throw_error(); - case MYSQL_NO_DATA: - complete_ = true; - return false; - } - return false; + LOG_VERBOSE; + + if (complete_) + return false; + + LOG_VERBOSE << "mysql_stmt_fetch()"; + int result = mysql_stmt_fetch(pStatement_); + + LOG_VERBOSE << result; + + switch (result) { + // We expect truncation whenever there's a string or blob + case MYSQL_DATA_TRUNCATED: + case 0: + return true; + case 1: + throw_error(); + case MYSQL_NO_DATA: + complete_ = true; + return false; + } + return false; } List MariaResultPrep::fetch(int n_max) { - if (!bound_) - stop("Query needs to be bound before fetching"); - if (!has_result()) { - if (names_.size() == 0) { - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and " - "also " - "avoid dbFetch()"); - } - return df_create(types_, names_, 0); - } - - int n = (n_max < 0) ? 100 : n_max; - List out = df_create(types_, names_, n); - if (n == 0) - return out; - - int i = 0; - - for (;;) { - if (i >= n && n_max > 0) - break; - - if (!step()) - break; - - if (i >= n) { - n *= 2; - out = df_resize(out, n); - } - - for (int j = 0; j < nCols_; ++j) { - // Rcout << i << "," << j << "\n"; - bindingOutput_.set_list_value(out[j], i, j); - } - - ++i; - if (i % 1024 == 0) - checkUserInterrupt(); - } - - // Trim back to what we actually used - if (i < n) { - out = df_resize(out, i); - } - // Set up S3 classes - df_s3(out, types_); - - return out; + if (!bound_) + stop("Query needs to be bound before fetching"); + if (!has_result()) { + if (names_.size() == 0) { + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and " + "also " + "avoid dbFetch()"); + } + return df_create(types_, names_, 0); + } + + int n = (n_max < 0) ? 100 : n_max; + List out = df_create(types_, names_, n); + if (n == 0) + return out; + + int i = 0; + + for (;;) { + if (i >= n && n_max > 0) + break; + + if (!step()) + break; + + if (i >= n) { + n *= 2; + out = df_resize(out, n); + } + + for (int j = 0; j < nCols_; ++j) { + // Rcout << i << "," << j << "\n"; + bindingOutput_.set_list_value(out[j], i, j); + } + + ++i; + if (i % 1024 == 0) + checkUserInterrupt(); + } + + // Trim back to what we actually used + if (i < n) { + out = df_resize(out, i); + } + // Set up S3 classes + df_s3(out, types_); + + return out; } int MariaResultPrep::n_rows_affected() { - if (!bound_) - return NA_INTEGER; - // FIXME: > 2^32 rows? - return static_cast(rowsAffected_); + if (!bound_) + return NA_INTEGER; + // FIXME: > 2^32 rows? + return static_cast(rowsAffected_); } int MariaResultPrep::n_rows_fetched() { - if (!bound_) - return 0; - // FIXME: > 2^32 rows? - return static_cast(rowsFetched_); + if (!bound_) + return 0; + // FIXME: > 2^32 rows? + return static_cast(rowsFetched_); } bool MariaResultPrep::complete() const { - if (!bound_) - return FALSE; - return !has_result() || // query doesn't have results - complete_; // we've fetched all available results + if (!bound_) + return FALSE; + return !has_result() || // query doesn't have results + complete_; // we've fetched all available results } void MariaResultPrep::throw_error() { - stop("%s [%i]", mysql_stmt_error(pStatement_), - mysql_stmt_errno(pStatement_)); + stop("%s [%i]", mysql_stmt_error(pStatement_), mysql_stmt_errno(pStatement_)); } void MariaResultPrep::cache_metadata() { - LOG_VERBOSE; + LOG_VERBOSE; - nCols_ = mysql_num_fields(pSpec_); - MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); + nCols_ = mysql_num_fields(pSpec_); + MYSQL_FIELD* fields = mysql_fetch_fields(pSpec_); - for (int i = 0; i < nCols_; ++i) { - names_.push_back(fields[i].name); + for (int i = 0; i < nCols_; ++i) { + names_.push_back(fields[i].name); - bool binary = fields[i].charsetnr == 63; - bool length1 = fields[i].length == 1; - MariaFieldType type = - variable_type_from_field_type(fields[i].type, binary, length1); - types_.push_back(type); + bool binary = fields[i].charsetnr == 63; + bool length1 = fields[i].length == 1; + MariaFieldType type = + variable_type_from_field_type(fields[i].type, binary, length1); + types_.push_back(type); - LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type - << ", " << binary << ") => " << type_name(type); - } + LOG_VERBOSE << i << " -> " << fields[i].name << "(" << fields[i].type + << ", " << binary << ") => " << type_name(type); + } } diff --git a/src/MariaResultPrep.h b/src/MariaResultPrep.h index f07ef302..c1fe8cb3 100644 --- a/src/MariaResultPrep.h +++ b/src/MariaResultPrep.h @@ -14,52 +14,52 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultPrep : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; - MYSQL_STMT* pStatement_; - MYSQL_RES* pSpec_; - uint64_t rowsAffected_, rowsFetched_; + MYSQL_STMT* pStatement_; + MYSQL_RES* pSpec_; + uint64_t rowsAffected_, rowsFetched_; - int nCols_, nParams_; - bool bound_, complete_; - bool is_statement_; + int nCols_, nParams_; + bool bound_, complete_; + bool is_statement_; - std::vector types_; - std::vector names_; - MariaBinding bindingInput_; - MariaRow bindingOutput_; + std::vector types_; + std::vector names_; + MariaBinding bindingInput_; + MariaRow bindingOutput_; -public: - MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); - ~MariaResultPrep(); + public: + MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement = false); + ~MariaResultPrep(); -public: - virtual void send_query(const std::string& sql); - virtual void close(); + public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; -public: - class UnsupportedPS : public std::exception {}; + public: + class UnsupportedPS : public std::exception {}; -private: - void execute(); + private: + void execute(); - bool has_result() const; - bool step(); - bool fetch_row(); - void NORET throw_error(); + bool has_result() const; + bool step(); + bool fetch_row(); + void NORET throw_error(); -private: - void cache_metadata(); + private: + void cache_metadata(); }; #endif diff --git a/src/MariaResultSimple.cpp b/src/MariaResultSimple.cpp index 1ffaebc0..77c98b83 100644 --- a/src/MariaResultSimple.cpp +++ b/src/MariaResultSimple.cpp @@ -6,60 +6,60 @@ MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement) : pConn_(pConn) { - (void)is_statement; + (void)is_statement; } MariaResultSimple::~MariaResultSimple() { - MariaResultSimple::close(); + MariaResultSimple::close(); } void MariaResultSimple::send_query(const std::string& sql) { - LOG_DEBUG << sql; + LOG_DEBUG << sql; - exec(sql); + exec(sql); } void MariaResultSimple::close() { - LOG_VERBOSE; + LOG_VERBOSE; } void MariaResultSimple::bind(const List& /*params*/) { - LOG_VERBOSE; + LOG_VERBOSE; - stop( - "This query is not supported by the prepared statement protocol, no " - "parameters can be bound."); + stop( + "This query is not supported by the prepared statement protocol, no " + "parameters can be bound."); } List MariaResultSimple::get_column_info() { - CharacterVector names(0), types(0); + CharacterVector names(0), types(0); - return List::create(_["name"] = names, _["type"] = types); + return List::create(_["name"] = names, _["type"] = types); } List MariaResultSimple::fetch(int /*n_max*/) { - LOG_VERBOSE; - - warning( - "Use dbExecute() instead of dbGetQuery() for statements, and also " - "avoid " - "dbFetch()"); - return df_create(std::vector(), std::vector(), - 0); + LOG_VERBOSE; + + warning( + "Use dbExecute() instead of dbGetQuery() for statements, and also " + "avoid " + "dbFetch()"); + return df_create(std::vector(), std::vector(), + 0); } int MariaResultSimple::n_rows_affected() { - return 0; + return 0; } int MariaResultSimple::n_rows_fetched() { - return 0; + return 0; } bool MariaResultSimple::complete() const { - return true; + return true; } void MariaResultSimple::exec(const std::string& sql) { - pConn_->exec(sql); + pConn_->exec(sql); } diff --git a/src/MariaResultSimple.h b/src/MariaResultSimple.h index 9cf0f846..242cfe69 100644 --- a/src/MariaResultSimple.h +++ b/src/MariaResultSimple.h @@ -14,28 +14,28 @@ class DbConnection; typedef boost::shared_ptr DbConnectionPtr; class MariaResultSimple : boost::noncopyable, public MariaResultImpl { - DbConnectionPtr pConn_; + DbConnectionPtr pConn_; -public: - MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); - ~MariaResultSimple(); + public: + MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement); + ~MariaResultSimple(); -public: - virtual void send_query(const std::string& sql); - virtual void close(); + public: + virtual void send_query(const std::string& sql); + virtual void close(); - virtual void bind(const List& params); + virtual void bind(const List& params); - virtual List get_column_info(); + virtual List get_column_info(); - virtual List fetch(int n_max = -1); + virtual List fetch(int n_max = -1); - virtual int n_rows_affected(); - virtual int n_rows_fetched(); - virtual bool complete() const; + virtual int n_rows_affected(); + virtual int n_rows_fetched(); + virtual bool complete() const; -private: - void exec(const std::string& sql); + private: + void exec(const std::string& sql); }; #endif diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index 998b6752..48d2ad49 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -13,245 +13,245 @@ MariaRow::~MariaRow() { void MariaRow::setup(MYSQL_STMT* pStatement, const std::vector& types) { - LOG_VERBOSE; - - pStatement_ = pStatement; - types_ = types; - n_ = static_cast(types_.size()); - - bindings_.resize(n_); - buffers_.resize(n_); - lengths_.resize(n_); - nulls_.resize(n_); - errors_.resize(n_); - - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << j << " -> " << type_name(types_[j]); - - // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html - switch (types_[j]) { - case MY_INT32: - bindings_[j].buffer_type = MYSQL_TYPE_LONG; - buffers_[j].resize(4); - break; - case MY_INT64: - bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; - buffers_[j].resize(8); - break; - case MY_DBL: - bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; - buffers_[j].resize(8); - break; - case MY_DATE: - bindings_[j].buffer_type = MYSQL_TYPE_DATE; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_DATE_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_TIME: - bindings_[j].buffer_type = MYSQL_TYPE_TIME; - buffers_[j].resize(sizeof(MYSQL_TIME)); - break; - case MY_STR: - bindings_[j].buffer_type = MYSQL_TYPE_STRING; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_RAW: - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(0); - // buffers might be arbitrary length, so leave size and use - // alternative strategy: see fetch_buffer() for details - break; - case MY_LGL: - // BIT(1) is bound to logical, in absence of dedicated type - bindings_[j].buffer_type = MYSQL_TYPE_BLOB; - buffers_[j].resize(4); - break; - } - - lengths_[j] = buffers_[j].size(); - bindings_[j].buffer_length = buffers_[j].size(); - if (bindings_[j].buffer_length > 0) - bindings_[j].buffer = &buffers_[j][0]; - else - bindings_[j].buffer = NULL; - bindings_[j].length = &lengths_[j]; - bindings_[j].is_null = &nulls_[j]; - bindings_[j].is_unsigned = true; - bindings_[j].error = &errors_[j]; - - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; - } - - LOG_DEBUG << "mysql_stmt_bind_result()"; - if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { - stop("Error binding result: %s", mysql_stmt_error(pStatement)); - } - - for (int j = 0; j < n_; ++j) { - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; - } + LOG_VERBOSE; + + pStatement_ = pStatement; + types_ = types; + n_ = static_cast(types_.size()); + + bindings_.resize(n_); + buffers_.resize(n_); + lengths_.resize(n_); + nulls_.resize(n_); + errors_.resize(n_); + + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << j << " -> " << type_name(types_[j]); + + // http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-type-codes.html + switch (types_[j]) { + case MY_INT32: + bindings_[j].buffer_type = MYSQL_TYPE_LONG; + buffers_[j].resize(4); + break; + case MY_INT64: + bindings_[j].buffer_type = MYSQL_TYPE_LONGLONG; + buffers_[j].resize(8); + break; + case MY_DBL: + bindings_[j].buffer_type = MYSQL_TYPE_DOUBLE; + buffers_[j].resize(8); + break; + case MY_DATE: + bindings_[j].buffer_type = MYSQL_TYPE_DATE; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_DATE_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_DATETIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_TIME: + bindings_[j].buffer_type = MYSQL_TYPE_TIME; + buffers_[j].resize(sizeof(MYSQL_TIME)); + break; + case MY_STR: + bindings_[j].buffer_type = MYSQL_TYPE_STRING; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_RAW: + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(0); + // buffers might be arbitrary length, so leave size and use + // alternative strategy: see fetch_buffer() for details + break; + case MY_LGL: + // BIT(1) is bound to logical, in absence of dedicated type + bindings_[j].buffer_type = MYSQL_TYPE_BLOB; + buffers_[j].resize(4); + break; + } + + lengths_[j] = buffers_[j].size(); + bindings_[j].buffer_length = buffers_[j].size(); + if (bindings_[j].buffer_length > 0) + bindings_[j].buffer = &buffers_[j][0]; + else + bindings_[j].buffer = NULL; + bindings_[j].length = &lengths_[j]; + bindings_[j].is_null = &nulls_[j]; + bindings_[j].is_unsigned = true; + bindings_[j].error = &errors_[j]; + + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; + } + + LOG_DEBUG << "mysql_stmt_bind_result()"; + if (mysql_stmt_bind_result(pStatement, &bindings_[0]) != 0) { + stop("Error binding result: %s", mysql_stmt_error(pStatement)); + } + + for (int j = 0; j < n_; ++j) { + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; + } } bool MariaRow::is_null(int j) { - return nulls_[j] == 1; + return nulls_[j] == 1; } int MariaRow::value_bool(int j) { - if (is_null(j)) { - return NA_LOGICAL; - } else { - return static_cast(value_int(j) == 1); - } + if (is_null(j)) { + return NA_LOGICAL; + } else { + return static_cast(value_int(j) == 1); + } } int MariaRow::value_int(int j) { - return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER : *((int*)&buffers_[j][0]); } int64_t MariaRow::value_int64(int j) { - return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); + return is_null(j) ? NA_INTEGER64 : *((int64_t*)&buffers_[j][0]); } double MariaRow::value_double(int j) { - return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); + return is_null(j) ? NA_REAL : *((double*)&buffers_[j][0]); } SEXP MariaRow::value_string(int j) { - if (is_null(j)) - return NA_STRING; + if (is_null(j)) + return NA_STRING; - fetch_buffer(j); - int len = static_cast(buffers_[j].size()); - if (len == 0) - return R_BlankString; + fetch_buffer(j); + int len = static_cast(buffers_[j].size()); + if (len == 0) + return R_BlankString; - const char* val = reinterpret_cast(&buffers_[j][0]); - return Rf_mkCharLenCE(val, len, CE_UTF8); + const char* val = reinterpret_cast(&buffers_[j][0]); + return Rf_mkCharLenCE(val, len, CE_UTF8); } SEXP MariaRow::value_raw(int j) { - if (is_null(j)) - return R_NilValue; + if (is_null(j)) + return R_NilValue; - fetch_buffer(j); - SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); - memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); + fetch_buffer(j); + SEXP bytes = Rf_allocVector(RAWSXP, lengths_[j]); + memcpy(RAW(bytes), &buffers_[j][0], lengths_[j]); - return bytes; + return bytes; } double MariaRow::value_date_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days) * 86400.0 + - static_cast(mytime->hour) * (60.0 * 60) + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; - LOG_VERBOSE << date_time; - return date_time; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days) * 86400.0 + + static_cast(mytime->hour) * (60.0 * 60) + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_date(int j) { - if (is_null(j)) - return NA_REAL; + if (is_null(j)) + return NA_REAL; - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - const int days = days_from_civil(mytime->year, mytime->month, mytime->day); - double date_time = static_cast(days); - LOG_VERBOSE << date_time; - return date_time; + const int days = days_from_civil(mytime->year, mytime->month, mytime->day); + double date_time = static_cast(days); + LOG_VERBOSE << date_time; + return date_time; } double MariaRow::value_time(int j) { - if (is_null(j)) - return NA_REAL; - - MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; - return static_cast(mytime->hour) * 3600.0 + - static_cast(mytime->minute) * 60.0 + - static_cast(mytime->second) + - static_cast(mytime->second_part) / 1000000.0; + if (is_null(j)) + return NA_REAL; + + MYSQL_TIME* mytime = (MYSQL_TIME*)&buffers_[j][0]; + return static_cast(mytime->hour) * 3600.0 + + static_cast(mytime->minute) * 60.0 + + static_cast(mytime->second) + + static_cast(mytime->second_part) / 1000000.0; } void MariaRow::set_list_value(SEXP x, int i, int j) { - switch (types_[j]) { - case MY_INT32: - INTEGER(x)[i] = value_int(j); - break; - case MY_INT64: - INTEGER64(x)[i] = value_int64(j); - break; - case MY_DBL: - REAL(x)[i] = value_double(j); - break; - case MY_DATE: - REAL(x)[i] = value_date(j); - break; - case MY_DATE_TIME: - REAL(x)[i] = value_date_time(j); - break; - case MY_TIME: - REAL(x)[i] = value_time(j); - break; - case MY_STR: - SET_STRING_ELT(x, i, value_string(j)); - break; - case MY_RAW: - SET_VECTOR_ELT(x, i, value_raw(j)); - break; - case MY_LGL: - LOGICAL(x)[i] = value_bool(j); - break; - } + switch (types_[j]) { + case MY_INT32: + INTEGER(x)[i] = value_int(j); + break; + case MY_INT64: + INTEGER64(x)[i] = value_int64(j); + break; + case MY_DBL: + REAL(x)[i] = value_double(j); + break; + case MY_DATE: + REAL(x)[i] = value_date(j); + break; + case MY_DATE_TIME: + REAL(x)[i] = value_date_time(j); + break; + case MY_TIME: + REAL(x)[i] = value_time(j); + break; + case MY_STR: + SET_STRING_ELT(x, i, value_string(j)); + break; + case MY_RAW: + SET_VECTOR_ELT(x, i, value_raw(j)); + break; + case MY_LGL: + LOGICAL(x)[i] = value_bool(j); + break; + } } void MariaRow::fetch_buffer(int j) { - unsigned long length = lengths_[j]; - LOG_VERBOSE << length; + unsigned long length = lengths_[j]; + LOG_VERBOSE << length; - buffers_[j].resize(length); - if (length == 0) - return; + buffers_[j].resize(length); + if (length == 0) + return; - bindings_[j].buffer = &buffers_[j][0]; // might have moved - bindings_[j].buffer_length = length; + bindings_[j].buffer = &buffers_[j][0]; // might have moved + bindings_[j].buffer_length = length; - LOG_VERBOSE << bindings_[j].buffer_length; - LOG_VERBOSE << bindings_[j].buffer; - LOG_VERBOSE << bindings_[j].length; - LOG_VERBOSE << (void*)bindings_[j].is_null; - LOG_VERBOSE << bindings_[j].is_unsigned; - LOG_VERBOSE << (void*)bindings_[j].error; + LOG_VERBOSE << bindings_[j].buffer_length; + LOG_VERBOSE << bindings_[j].buffer; + LOG_VERBOSE << bindings_[j].length; + LOG_VERBOSE << (void*)bindings_[j].is_null; + LOG_VERBOSE << bindings_[j].is_unsigned; + LOG_VERBOSE << (void*)bindings_[j].error; - LOG_DEBUG << "mysql_stmt_fetch_column()"; - int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); - LOG_VERBOSE << result; + LOG_DEBUG << "mysql_stmt_fetch_column()"; + int result = mysql_stmt_fetch_column(pStatement_, &bindings_[j], j, 0); + LOG_VERBOSE << result; - if (result != 0) - stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); + if (result != 0) + stop("Error fetching buffer: %s", mysql_stmt_error(pStatement_)); - // Reset buffer length to zero for next row - bindings_[j].buffer = NULL; - bindings_[j].buffer_length = 0; + // Reset buffer length to zero for next row + bindings_[j].buffer = NULL; + bindings_[j].buffer_length = 0; } diff --git a/src/MariaRow.h b/src/MariaRow.h index 553edd02..45efd3b5 100644 --- a/src/MariaRow.h +++ b/src/MariaRow.h @@ -8,41 +8,40 @@ #include "MariaTypes.h" class MariaRow : public boost::noncopyable { - MYSQL_STMT* pStatement_; - - int n_; - std::vector bindings_; - - std::vector types_; - std::vector > buffers_; - std::vector lengths_; - boost::container::vector nulls_, errors_; - -public: - MariaRow(); - ~MariaRow(); - -public: - void setup(MYSQL_STMT* pStatement, - const std::vector& types); - void set_list_value(SEXP x, int i, int j); - -private: - // Value accessors - // ----------------------------------------------------------- - bool is_null(int j); - - int value_int(int j); - int value_bool(int j); - int64_t value_int64(int j); - double value_double(int j); - SEXP value_string(int j); - SEXP value_raw(int j); - double value_date_time(int j); - double value_date(int j); - double value_time(int j); - - void fetch_buffer(int j); + MYSQL_STMT* pStatement_; + + int n_; + std::vector bindings_; + + std::vector types_; + std::vector > buffers_; + std::vector lengths_; + boost::container::vector nulls_, errors_; + + public: + MariaRow(); + ~MariaRow(); + + public: + void setup(MYSQL_STMT* pStatement, const std::vector& types); + void set_list_value(SEXP x, int i, int j); + + private: + // Value accessors + // ----------------------------------------------------------- + bool is_null(int j); + + int value_int(int j); + int value_bool(int j); + int64_t value_int64(int j); + double value_double(int j); + SEXP value_string(int j); + SEXP value_raw(int j); + double value_date_time(int j); + double value_date(int j); + double value_time(int j); + + void fetch_buffer(int j); }; #endif diff --git a/src/MariaTypes.cpp b/src/MariaTypes.cpp index 746b5f09..be2c666c 100644 --- a/src/MariaTypes.cpp +++ b/src/MariaTypes.cpp @@ -7,157 +7,157 @@ bool all_raw(SEXP x); MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, bool length1) { - switch (type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_YEAR: - return MY_INT32; + switch (type) { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_YEAR: + return MY_INT32; - case MYSQL_TYPE_LONGLONG: - return MY_INT64; + case MYSQL_TYPE_LONGLONG: + return MY_INT64; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - return MY_DBL; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - return MY_DATE_TIME; - case MYSQL_TYPE_DATE: - return MY_DATE; - case MYSQL_TYPE_TIME: - return MY_TIME; - case MYSQL_TYPE_BIT: - if (length1) { - return MY_LGL; - } - // fallthrough - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - return binary ? MY_RAW : MY_STR; - case MYSQL_TYPE_SET: - return MY_STR; - case MYSQL_TYPE_GEOMETRY: - return MY_RAW; - case MYSQL_TYPE_NULL: - return MY_INT32; - default: - throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); - } + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + return MY_DBL; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_NEWDATE: + return MY_DATE_TIME; + case MYSQL_TYPE_DATE: + return MY_DATE; + case MYSQL_TYPE_TIME: + return MY_TIME; + case MYSQL_TYPE_BIT: + if (length1) { + return MY_LGL; + } + // fallthrough + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + return binary ? MY_RAW : MY_STR; + case MYSQL_TYPE_SET: + return MY_STR; + case MYSQL_TYPE_GEOMETRY: + return MY_RAW; + case MYSQL_TYPE_NULL: + return MY_INT32; + default: + throw std::runtime_error("Unimplemented MAX_NO_FIELD_TYPES"); + } } std::string type_name(MariaFieldType type) { - switch (type) { - case MY_INT32: - return "integer"; - case MY_INT64: - return "integer64"; - case MY_DBL: - return "double"; - case MY_STR: - return "string"; - case MY_DATE: - return "Date"; - case MY_DATE_TIME: - return "POSIXct"; - case MY_TIME: - return "hms"; - case MY_RAW: - return "raw"; - case MY_LGL: - return "logical"; - } - throw std::runtime_error("Invalid typeName"); + switch (type) { + case MY_INT32: + return "integer"; + case MY_INT64: + return "integer64"; + case MY_DBL: + return "double"; + case MY_STR: + return "string"; + case MY_DATE: + return "Date"; + case MY_DATE_TIME: + return "POSIXct"; + case MY_TIME: + return "hms"; + case MY_RAW: + return "raw"; + case MY_LGL: + return "logical"; + } + throw std::runtime_error("Invalid typeName"); } SEXPTYPE type_sexp(MariaFieldType type) { - switch (type) { - case MY_INT32: - return INTSXP; - case MY_INT64: - return INT64SXP; - case MY_DBL: - return REALSXP; - case MY_STR: - return STRSXP; - case MY_DATE: - return REALSXP; - case MY_DATE_TIME: - return REALSXP; - case MY_TIME: - return REALSXP; - case MY_RAW: - return VECSXP; - case MY_LGL: - return LGLSXP; - } - throw std::runtime_error("Invalid typeSEXP"); + switch (type) { + case MY_INT32: + return INTSXP; + case MY_INT64: + return INT64SXP; + case MY_DBL: + return REALSXP; + case MY_STR: + return STRSXP; + case MY_DATE: + return REALSXP; + case MY_DATE_TIME: + return REALSXP; + case MY_TIME: + return REALSXP; + case MY_RAW: + return VECSXP; + case MY_LGL: + return LGLSXP; + } + throw std::runtime_error("Invalid typeSEXP"); } std::string r_class(RObject x) { - RObject klass_(x.attr("class")); - std::string klass; - if (klass_ == R_NilValue) - return ""; + RObject klass_(x.attr("class")); + std::string klass; + if (klass_ == R_NilValue) + return ""; - CharacterVector klassv = as(klass_); - return std::string(klassv[klassv.length() - 1]); + CharacterVector klassv = as(klass_); + return std::string(klassv[klassv.length() - 1]); } MariaFieldType variable_type_from_object(const RObject& type) { - std::string klass = r_class(type); + std::string klass = r_class(type); - switch (TYPEOF(type)) { - case LGLSXP: - return MY_LGL; - case INTSXP: - return MY_INT32; - case REALSXP: - if (klass == "Date") - return MY_DATE; - if (klass == "POSIXt") - return MY_DATE_TIME; - if (klass == "difftime") - return MY_TIME; - if (klass == "integer64") - return MY_INT64; - return MY_DBL; - case STRSXP: - return MY_STR; - case VECSXP: - if (klass == "blob") - return MY_RAW; - if (all_raw(type)) - return MY_RAW; - break; - } + switch (TYPEOF(type)) { + case LGLSXP: + return MY_LGL; + case INTSXP: + return MY_INT32; + case REALSXP: + if (klass == "Date") + return MY_DATE; + if (klass == "POSIXt") + return MY_DATE_TIME; + if (klass == "difftime") + return MY_TIME; + if (klass == "integer64") + return MY_INT64; + return MY_DBL; + case STRSXP: + return MY_STR; + case VECSXP: + if (klass == "blob") + return MY_RAW; + if (all_raw(type)) + return MY_RAW; + break; + } - stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); - return MY_STR; + stop("Unsupported column type %s", Rf_type2char(TYPEOF(type))); + return MY_STR; } bool all_raw(SEXP x) { - List xx(x); - for (R_xlen_t i = 0; i < xx.length(); ++i) { - switch (TYPEOF(xx[i])) { - case RAWSXP: - case NILSXP: - break; + List xx(x); + for (R_xlen_t i = 0; i < xx.length(); ++i) { + switch (TYPEOF(xx[i])) { + case RAWSXP: + case NILSXP: + break; - default: - return false; - } - } - return true; + default: + return false; + } + } + return true; } diff --git a/src/MariaTypes.h b/src/MariaTypes.h index 8d3fd866..df681f7f 100644 --- a/src/MariaTypes.h +++ b/src/MariaTypes.h @@ -2,15 +2,15 @@ #define __RMARIADB_MARIA_TYPES__ enum MariaFieldType { - MY_INT32, - MY_INT64, // output only - MY_DBL, - MY_STR, - MY_DATE, - MY_DATE_TIME, - MY_TIME, - MY_RAW, - MY_LGL // for BIT(1) + MY_INT32, + MY_INT64, // output only + MY_DBL, + MY_STR, + MY_DATE, + MY_DATE_TIME, + MY_TIME, + MY_RAW, + MY_LGL // for BIT(1) }; MariaFieldType variable_type_from_field_type(enum_field_types type, bool binary, diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 0aae55fc..d772fcae 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -29,271 +29,270 @@ RcppExport SEXP _RMariaDB_connection_create( SEXP default_fileSEXP, SEXP ssl_keySEXP, SEXP ssl_certSEXP, SEXP ssl_caSEXP, SEXP ssl_capathSEXP, SEXP ssl_cipherSEXP, SEXP timeoutSEXP, SEXP reconnectSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter&>::type host( - hostSEXP); - Rcpp::traits::input_parameter&>::type user( - userSEXP); - Rcpp::traits::input_parameter&>::type password( - passwordSEXP); - Rcpp::traits::input_parameter&>::type db( - dbSEXP); - Rcpp::traits::input_parameter::type port(portSEXP); - Rcpp::traits::input_parameter&>::type - unix_socket(unix_socketSEXP); - Rcpp::traits::input_parameter::type client_flag( - client_flagSEXP); - Rcpp::traits::input_parameter&>::type groups( - groupsSEXP); - Rcpp::traits::input_parameter&>::type - default_file(default_fileSEXP); - Rcpp::traits::input_parameter&>::type ssl_key( - ssl_keySEXP); - Rcpp::traits::input_parameter&>::type ssl_cert( - ssl_certSEXP); - Rcpp::traits::input_parameter&>::type ssl_ca( - ssl_caSEXP); - Rcpp::traits::input_parameter&>::type - ssl_capath(ssl_capathSEXP); - Rcpp::traits::input_parameter&>::type - ssl_cipher(ssl_cipherSEXP); - Rcpp::traits::input_parameter::type timeout(timeoutSEXP); - Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); - rcpp_result_gen = Rcpp::wrap( - connection_create(host, user, password, db, port, unix_socket, - client_flag, groups, default_file, ssl_key, ssl_cert, - ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter&>::type host( + hostSEXP); + Rcpp::traits::input_parameter&>::type user( + userSEXP); + Rcpp::traits::input_parameter&>::type password( + passwordSEXP); + Rcpp::traits::input_parameter&>::type db(dbSEXP); + Rcpp::traits::input_parameter::type port(portSEXP); + Rcpp::traits::input_parameter&>::type unix_socket( + unix_socketSEXP); + Rcpp::traits::input_parameter::type client_flag( + client_flagSEXP); + Rcpp::traits::input_parameter&>::type groups( + groupsSEXP); + Rcpp::traits::input_parameter&>::type + default_file(default_fileSEXP); + Rcpp::traits::input_parameter&>::type ssl_key( + ssl_keySEXP); + Rcpp::traits::input_parameter&>::type ssl_cert( + ssl_certSEXP); + Rcpp::traits::input_parameter&>::type ssl_ca( + ssl_caSEXP); + Rcpp::traits::input_parameter&>::type ssl_capath( + ssl_capathSEXP); + Rcpp::traits::input_parameter&>::type ssl_cipher( + ssl_cipherSEXP); + Rcpp::traits::input_parameter::type timeout(timeoutSEXP); + Rcpp::traits::input_parameter::type reconnect(reconnectSEXP); + rcpp_result_gen = Rcpp::wrap( + connection_create(host, user, password, db, port, unix_socket, + client_flag, groups, default_file, ssl_key, ssl_cert, + ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect)); + return rcpp_result_gen; + END_RCPP } // connection_valid bool connection_valid(XPtr con_); RcppExport SEXP _RMariaDB_connection_valid(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + rcpp_result_gen = Rcpp::wrap(connection_valid(con_)); + return rcpp_result_gen; + END_RCPP } // connection_release void connection_release(XPtr con_); RcppExport SEXP _RMariaDB_connection_release(SEXP con_SEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con_(con_SEXP); - connection_release(con_); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con_(con_SEXP); + connection_release(con_); + return R_NilValue; + END_RCPP } // connection_info List connection_info(DbConnection* con); RcppExport SEXP _RMariaDB_connection_info(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_info(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_info(con)); + return rcpp_result_gen; + END_RCPP } // connection_quote_string CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs); RcppExport SEXP _RMariaDB_connection_quote_string(SEXP conSEXP, SEXP xsSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - Rcpp::traits::input_parameter::type xs(xsSEXP); - rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + Rcpp::traits::input_parameter::type xs(xsSEXP); + rcpp_result_gen = Rcpp::wrap(connection_quote_string(con, xs)); + return rcpp_result_gen; + END_RCPP } // connection_begin_transaction void connection_begin_transaction(XPtr con); RcppExport SEXP _RMariaDB_connection_begin_transaction(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_begin_transaction(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_begin_transaction(con); + return R_NilValue; + END_RCPP } // connection_commit void connection_commit(XPtr con); RcppExport SEXP _RMariaDB_connection_commit(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_commit(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_commit(con); + return R_NilValue; + END_RCPP } // connection_rollback void connection_rollback(XPtr con); RcppExport SEXP _RMariaDB_connection_rollback(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - connection_rollback(con); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + connection_rollback(con); + return R_NilValue; + END_RCPP } // connection_is_transacting bool connection_is_transacting(DbConnection* con); RcppExport SEXP _RMariaDB_connection_is_transacting(SEXP conSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type con(conSEXP); - rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type con(conSEXP); + rcpp_result_gen = Rcpp::wrap(connection_is_transacting(con)); + return rcpp_result_gen; + END_RCPP } // driver_init void driver_init(); RcppExport SEXP _RMariaDB_driver_init() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_init(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_init(); + return R_NilValue; + END_RCPP } // driver_done void driver_done(); RcppExport SEXP _RMariaDB_driver_done() { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - driver_done(); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + driver_done(); + return R_NilValue; + END_RCPP } // version IntegerVector version(); RcppExport SEXP _RMariaDB_version() { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - rcpp_result_gen = Rcpp::wrap(version()); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = Rcpp::wrap(version()); + return rcpp_result_gen; + END_RCPP } // init_logging void init_logging(const std::string& log_level); RcppExport SEXP _RMariaDB_init_logging(SEXP log_levelSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type log_level( - log_levelSEXP); - init_logging(log_level); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type log_level( + log_levelSEXP); + init_logging(log_level); + return R_NilValue; + END_RCPP } // result_create XPtr result_create(XPtr con, std::string sql, bool is_statement); RcppExport SEXP _RMariaDB_result_create(SEXP conSEXP, SEXP sqlSEXP, SEXP is_statementSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type con(conSEXP); - Rcpp::traits::input_parameter::type sql(sqlSEXP); - Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); - rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type con(conSEXP); + Rcpp::traits::input_parameter::type sql(sqlSEXP); + Rcpp::traits::input_parameter::type is_statement(is_statementSEXP); + rcpp_result_gen = Rcpp::wrap(result_create(con, sql, is_statement)); + return rcpp_result_gen; + END_RCPP } // result_release void result_release(XPtr res); RcppExport SEXP _RMariaDB_result_release(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res(resSEXP); - result_release(res); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res(resSEXP); + result_release(res); + return R_NilValue; + END_RCPP } // result_valid bool result_valid(XPtr res_); RcppExport SEXP _RMariaDB_result_valid(SEXP res_SEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter >::type res_(res_SEXP); - rcpp_result_gen = Rcpp::wrap(result_valid(res_)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter >::type res_(res_SEXP); + rcpp_result_gen = Rcpp::wrap(result_valid(res_)); + return rcpp_result_gen; + END_RCPP } // result_fetch List result_fetch(DbResult* res, const int n); RcppExport SEXP _RMariaDB_result_fetch(SEXP resSEXP, SEXP nSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type n(nSEXP); - rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type n(nSEXP); + rcpp_result_gen = Rcpp::wrap(result_fetch(res, n)); + return rcpp_result_gen; + END_RCPP } // result_bind void result_bind(DbResult* res, List params); RcppExport SEXP _RMariaDB_result_bind(SEXP resSEXP, SEXP paramsSEXP) { - BEGIN_RCPP - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - Rcpp::traits::input_parameter::type params(paramsSEXP); - result_bind(res, params); - return R_NilValue; - END_RCPP + BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + Rcpp::traits::input_parameter::type params(paramsSEXP); + result_bind(res, params); + return R_NilValue; + END_RCPP } // result_has_completed bool result_has_completed(DbResult* res); RcppExport SEXP _RMariaDB_result_has_completed(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_has_completed(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_fetched int result_rows_fetched(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_fetched(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_fetched(res)); + return rcpp_result_gen; + END_RCPP } // result_rows_affected int result_rows_affected(DbResult* res); RcppExport SEXP _RMariaDB_result_rows_affected(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_rows_affected(res)); + return rcpp_result_gen; + END_RCPP } // result_column_info List result_column_info(DbResult* res); RcppExport SEXP _RMariaDB_result_column_info(SEXP resSEXP) { - BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter::type res(resSEXP); - rcpp_result_gen = Rcpp::wrap(result_column_info(res)); - return rcpp_result_gen; - END_RCPP + BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter::type res(resSEXP); + rcpp_result_gen = Rcpp::wrap(result_column_info(res)); + return rcpp_result_gen; + END_RCPP } static const R_CallMethodDef CallEntries[] = { @@ -329,6 +328,6 @@ static const R_CallMethodDef CallEntries[] = { {NULL, NULL, 0}}; RcppExport void R_init_RMariaDB(DllInfo* dll) { - R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); - R_useDynamicSymbols(dll, FALSE); + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); } diff --git a/src/connection.cpp b/src/connection.cpp index 7a8d17af..14e4fcbf 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -12,81 +12,81 @@ XPtr connection_create( const Nullable& ssl_ca, const Nullable& ssl_capath, const Nullable& ssl_cipher, int timeout, bool reconnect) { - LOG_VERBOSE; + LOG_VERBOSE; - DbConnection* pConnPtr = new DbConnection; - try { - pConnPtr->connect(host, user, password, db, port, unix_socket, - client_flag, groups, default_file, ssl_key, ssl_cert, - ssl_ca, ssl_capath, ssl_cipher, timeout, reconnect); - } catch (...) { - delete pConnPtr; - throw; - } + DbConnection* pConnPtr = new DbConnection; + try { + pConnPtr->connect(host, user, password, db, port, unix_socket, client_flag, + groups, default_file, ssl_key, ssl_cert, ssl_ca, + ssl_capath, ssl_cipher, timeout, reconnect); + } catch (...) { + delete pConnPtr; + throw; + } - DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); + DbConnectionPtr* pConn = new DbConnectionPtr(pConnPtr); - return XPtr(pConn, true); + return XPtr(pConn, true); } // [[Rcpp::export]] bool connection_valid(XPtr con_) { - DbConnectionPtr* con = con_.get(); - return con && con->get()->is_valid(); + DbConnectionPtr* con = con_.get(); + return con && con->get()->is_valid(); } // [[Rcpp::export]] void connection_release(XPtr con_) { - if (!connection_valid(con_)) { - warning("Already disconnected"); - return; - } - - DbConnectionPtr* con = con_.get(); - con->get()->disconnect(); - con_.release(); + if (!connection_valid(con_)) { + warning("Already disconnected"); + return; + } + + DbConnectionPtr* con = con_.get(); + con->get()->disconnect(); + con_.release(); } // [[Rcpp::export]] List connection_info(DbConnection* con) { - return con->info(); + return con->info(); } // Quoting // [[Rcpp::export]] CharacterVector connection_quote_string(DbConnection* con, CharacterVector xs) { - R_xlen_t n = xs.size(); - CharacterVector output(n); + R_xlen_t n = xs.size(); + CharacterVector output(n); - for (R_xlen_t i = 0; i < n; ++i) { - String x = xs[i]; - output[i] = con->quote_string(x); - } + for (R_xlen_t i = 0; i < n; ++i) { + String x = xs[i]; + output[i] = con->quote_string(x); + } - return output; + return output; } // Transactions // [[Rcpp::export]] void connection_begin_transaction(XPtr con) { - (*con)->begin_transaction(); + (*con)->begin_transaction(); } // [[Rcpp::export]] void connection_commit(XPtr con) { - (*con)->commit(); + (*con)->commit(); } // [[Rcpp::export]] void connection_rollback(XPtr con) { - (*con)->rollback(); + (*con)->rollback(); } // [[Rcpp::export]] bool connection_is_transacting(DbConnection* con) { - return con->is_transacting(); + return con->is_transacting(); } // Specific functions @@ -97,10 +97,10 @@ namespace Rcpp { template <> DbConnection* as(SEXP x) { - DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); - if (!connection) - stop("Invalid connection"); - return connection->get(); + DbConnectionPtr* connection = (DbConnectionPtr*)(R_ExternalPtrAddr(x)); + if (!connection) + stop("Invalid connection"); + return connection->get(); } } // namespace Rcpp diff --git a/src/driver.cpp b/src/driver.cpp index 5c05fbbe..aa940f86 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -10,22 +10,22 @@ // [[Rcpp::export]] void driver_init() { - mysql_library_init(0, NULL, NULL); + mysql_library_init(0, NULL, NULL); } // [[Rcpp::export]] void driver_done() { - mysql_library_end(); + mysql_library_end(); } // [[Rcpp::export]] IntegerVector version() { - return IntegerVector::create( - _[SERVER_VERSION] = MYSQL_VERSION_ID, - _[mysql_get_client_info()] = mysql_get_client_version()); + return IntegerVector::create( + _[SERVER_VERSION] = MYSQL_VERSION_ID, + _[mysql_get_client_info()] = mysql_get_client_version()); } // [[Rcpp::export]] void init_logging(const std::string& log_level) { - plog::init_r(log_level); + plog::init_r(log_level); } diff --git a/src/integer64.h b/src/integer64.h index 2b0a6f42..2f3b934c 100644 --- a/src/integer64.h +++ b/src/integer64.h @@ -6,7 +6,7 @@ #define NA_INTEGER64 (static_cast(0x8000000000000000)) inline int64_t* INTEGER64(SEXP x) { - return reinterpret_cast(REAL(x)); + return reinterpret_cast(REAL(x)); } #endif // RMARIADB_INTEGER64_H diff --git a/src/result.cpp b/src/result.cpp index 38a448fa..6a11326b 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -5,60 +5,60 @@ // [[Rcpp::export]] XPtr result_create(XPtr con, std::string sql, bool is_statement = false) { - (*con)->check_connection(); - DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); - return XPtr(res, true); + (*con)->check_connection(); + DbResult* res = MariaResult::create_and_send_query(*con, sql, is_statement); + return XPtr(res, true); } // [[Rcpp::export]] void result_release(XPtr res) { - res.release(); + res.release(); } // [[Rcpp::export]] bool result_valid(XPtr res_) { - DbResult* res = res_.get(); - return res != NULL && res->is_active(); + DbResult* res = res_.get(); + return res != NULL && res->is_active(); } // [[Rcpp::export]] List result_fetch(DbResult* res, const int n) { - return res->fetch(n); + return res->fetch(n); } // [[Rcpp::export]] void result_bind(DbResult* res, List params) { - res->bind(params); + res->bind(params); } // [[Rcpp::export]] bool result_has_completed(DbResult* res) { - return res->complete(); + return res->complete(); } // [[Rcpp::export]] int result_rows_fetched(DbResult* res) { - return res->n_rows_fetched(); + return res->n_rows_fetched(); } // [[Rcpp::export]] int result_rows_affected(DbResult* res) { - return res->n_rows_affected(); + return res->n_rows_affected(); } // [[Rcpp::export]] List result_column_info(DbResult* res) { - return res->get_column_info(); + return res->get_column_info(); } namespace Rcpp { template <> DbResult* as(SEXP x) { - DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); - if (!result) - stop("Invalid result set"); - return result; + DbResult* result = (DbResult*)(R_ExternalPtrAddr(x)); + if (!result) + stop("Invalid result set"); + return result; } } // namespace Rcpp From 5bfa766de01fa797f0fa1bd645d841fe792ff421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 9 Dec 2022 16:26:35 +0000 Subject: [PATCH 9/9] include pch.h first --- .clang-format | 3 +++ src/DbConnection.cpp | 3 ++- src/DbResult.cpp | 3 ++- src/MariaBinding.cpp | 3 ++- src/MariaResult.cpp | 3 ++- src/MariaResultImpl.cpp | 4 ++-- src/MariaResultPrep.cpp | 3 ++- src/MariaResultSimple.cpp | 3 ++- src/MariaRow.cpp | 3 ++- src/MariaTypes.cpp | 3 ++- src/connection.cpp | 3 ++- src/result.cpp | 3 ++- 12 files changed, 25 insertions(+), 12 deletions(-) diff --git a/.clang-format b/.clang-format index 3b33b163..e2eac569 100644 --- a/.clang-format +++ b/.clang-format @@ -7,3 +7,6 @@ IndentCaseLabels: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never AccessModifierOffset: -4 +IncludeCategories: + - Regex: '^((<|")(pch.h))' + Priority: -1 diff --git a/src/DbConnection.cpp b/src/DbConnection.cpp index b228c2c5..d6a4202c 100644 --- a/src/DbConnection.cpp +++ b/src/DbConnection.cpp @@ -1,7 +1,8 @@ +#include "pch.h" + #include "DbConnection.h" #include "DbResult.h" -#include "pch.h" DbConnection::DbConnection() : pConn_(NULL), pCurrentResult_(NULL), transacting_(false) { diff --git a/src/DbResult.cpp b/src/DbResult.cpp index a6e5a23c..b425a314 100644 --- a/src/DbResult.cpp +++ b/src/DbResult.cpp @@ -1,8 +1,9 @@ +#include "pch.h" + #include "DbResult.h" #include "DbConnection.h" #include "DbResultImpl.h" -#include "pch.h" // Construction //////////////////////////////////////////////////////////////// diff --git a/src/MariaBinding.cpp b/src/MariaBinding.cpp index a7006b2f..31a805cb 100644 --- a/src/MariaBinding.cpp +++ b/src/MariaBinding.cpp @@ -1,9 +1,10 @@ +#include "pch.h" + #include "MariaBinding.h" #include #include "integer64.h" -#include "pch.h" MariaBinding::MariaBinding() : statement(NULL), p(0), i(0), n_rows(0) { } diff --git a/src/MariaResult.cpp b/src/MariaResult.cpp index 3ff33974..017036b5 100644 --- a/src/MariaResult.cpp +++ b/src/MariaResult.cpp @@ -1,8 +1,9 @@ +#include "pch.h" + #include "MariaResult.h" #include "MariaResultPrep.h" #include "MariaResultSimple.h" -#include "pch.h" // Construction //////////////////////////////////////////////////////////////// diff --git a/src/MariaResultImpl.cpp b/src/MariaResultImpl.cpp index 8082f1a0..92fea7c1 100644 --- a/src/MariaResultImpl.cpp +++ b/src/MariaResultImpl.cpp @@ -1,7 +1,7 @@ -#include "MariaResultImpl.h" - #include "pch.h" +#include "MariaResultImpl.h" + MariaResultImpl::MariaResultImpl() { } diff --git a/src/MariaResultPrep.cpp b/src/MariaResultPrep.cpp index 5e2434f9..27d23310 100644 --- a/src/MariaResultPrep.cpp +++ b/src/MariaResultPrep.cpp @@ -1,10 +1,11 @@ +#include "pch.h" + #include "MariaResultPrep.h" #include #include "DbConnection.h" #include "MariaResult.h" -#include "pch.h" MariaResultPrep::MariaResultPrep(const DbConnectionPtr& pConn, bool is_statement) diff --git a/src/MariaResultSimple.cpp b/src/MariaResultSimple.cpp index 77c98b83..dd13333e 100644 --- a/src/MariaResultSimple.cpp +++ b/src/MariaResultSimple.cpp @@ -1,7 +1,8 @@ +#include "pch.h" + #include "MariaResultSimple.h" #include "DbConnection.h" -#include "pch.h" MariaResultSimple::MariaResultSimple(const DbConnectionPtr& pConn, bool is_statement) diff --git a/src/MariaRow.cpp b/src/MariaRow.cpp index 48d2ad49..e5944b90 100644 --- a/src/MariaRow.cpp +++ b/src/MariaRow.cpp @@ -1,9 +1,10 @@ +#include "pch.h" + #include "MariaRow.h" #include "MariaTypes.h" #include "MariaUtils.h" #include "integer64.h" -#include "pch.h" MariaRow::MariaRow() : pStatement_(NULL), n_(0) { } diff --git a/src/MariaTypes.cpp b/src/MariaTypes.cpp index be2c666c..37c37162 100644 --- a/src/MariaTypes.cpp +++ b/src/MariaTypes.cpp @@ -1,7 +1,8 @@ +#include "pch.h" + #include "MariaTypes.h" #include "integer64.h" -#include "pch.h" bool all_raw(SEXP x); diff --git a/src/connection.cpp b/src/connection.cpp index 14e4fcbf..e350ecee 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1,6 +1,7 @@ -#include "RMariaDB_types.h" #include "pch.h" +#include "RMariaDB_types.h" + // [[Rcpp::export]] XPtr connection_create( const Nullable& host, const Nullable& user, diff --git a/src/result.cpp b/src/result.cpp index 6a11326b..0ae16f0d 100644 --- a/src/result.cpp +++ b/src/result.cpp @@ -1,6 +1,7 @@ +#include "pch.h" + #include "MariaResult.h" #include "RMariaDB_types.h" -#include "pch.h" // [[Rcpp::export]] XPtr result_create(XPtr con, std::string sql,