/** * Sets standard db options in a dbi_conn. * * @param qbe QOF backend * @param conn dbi_conn connection * @param uri UriStrings containing the needed paramters. * @return TRUE if successful, FALSE if error */ static bool set_standard_connection_options (QofBackend* qbe, dbi_conn conn, const UriStrings& uri) { gint result; PairVec options; options.push_back(std::make_pair("host", uri.m_host)); options.push_back(std::make_pair("dbname", uri.m_dbname)); options.push_back(std::make_pair("username", uri.m_username)); options.push_back(std::make_pair("password", uri.m_password)); options.push_back(std::make_pair("encoding", "UTF-8")); try { set_options(conn, options); auto result = dbi_conn_set_option_numeric(conn, "port", uri.m_portnum); if (result < 0) { const char *msg = nullptr; auto err = dbi_conn_error(conn, &msg); PERR("Error setting port option to %d: %s", uri.m_portnum, msg); throw std::runtime_error(msg); } } catch (std::runtime_error& err) { qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return false; } return true; }
static bool create_database(DbType type, QofBackend *qbe, dbi_conn conn, const char* db) { const char *dbname; const char *dbcreate; if (type == DbType::DBI_MYSQL) { dbname = "mysql"; dbcreate = "CREATE DATABASE %s CHARACTER SET utf8"; } else { dbname = "postgres"; dbcreate = "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'"; } PairVec options; options.push_back(std::make_pair("dbname", dbname)); try { set_options(conn, options); } catch (std::runtime_error& err) { qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return false; } auto result = dbi_conn_connect (conn); if (result < 0) { PERR ("Unable to connect to %s database", dbname); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return false; } if (type == DbType::DBI_MYSQL) adjust_sql_options(conn); auto dresult = dbi_conn_queryf (conn, dbcreate, db); if (dresult == nullptr) { PERR ("Unable to create database '%s'\n", db); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return false; } if (type == DbType::DBI_PGSQL) { const char *alterdb = "ALTER DATABASE %s SET " "standard_conforming_strings TO on"; dbi_conn_queryf (conn, alterdb, db); } dbi_conn_close(conn); conn = nullptr; return true; }
// sort freq order void term(int lowerLimit = 3, double upperRateLimit = 0.98) { fprintf(stderr, "#doc=%d, #word=%d\n", docNum_, (int)df_.size()); for (size_t i = 0, n = id2word_.size(); i < n; i++) { const int freq = df_[i]; if (freq <= lowerLimit) continue; pv_.push_back(Pair(i, freq)); } int pvNum = (int)(pv_.size() * upperRateLimit); fprintf(stderr, "shrink %d -> %d\n", (int)pv_.size(), pvNum); std::partial_sort(pv_.begin(), pv_.begin() + pvNum, pv_.end()); pv_.resize(pvNum); }
template <DbType Type> dbi_conn conn_setup (QofBackend* qbe, PairVec& options, UriStrings& uri) { const char* dbstr = (Type == DbType::DBI_SQLITE ? "sqlite3" : Type == DbType::DBI_MYSQL ? "mysql" : "pgsql"); #if HAVE_LIBDBI_R dbi_conn conn = nullptr; if (dbi_instance) conn = dbi_conn_new_r (dbstr, dbi_instance); else PERR ("Attempt to connect with an uninitialized dbi_instance"); #else auto conn = dbi_conn_new (dbstr); #endif if (conn == nullptr) { PERR ("Unable to create %s dbi connection", dbstr); qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL); return nullptr; } dbi_conn_error_handler (conn, error_handler<Type>, qbe); if (!uri.m_dbname.empty() && !set_standard_connection_options(qbe, conn, uri)) { dbi_conn_close(conn); return nullptr; } if(!options.empty()) { try { set_options(conn, options); } catch (std::runtime_error& err) { dbi_conn_close(conn); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return nullptr; } } return conn; }
/* char is unusual in that we get a pointer but don't deref it to pass * it to operator<<(). */ template<> void GncSqlColumnTableEntryImpl<CT_ADDRESS>::add_to_query(QofIdTypeConst obj_name, const gpointer pObject, PairVec& vec) const noexcept { auto addr(get_row_value_from_object<char*>(obj_name, pObject)); if (addr == nullptr) return; for (auto const& subtable_row : col_table) { auto s = subtable_row->get_row_value_from_object<char*>(GNC_ID_ADDRESS, addr); if (s == nullptr) continue; auto buf = std::string{m_col_name} + "_" + subtable_row->m_col_name; vec.emplace_back(make_pair(buf, std::string(s))); } }
template <> void gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session, const char* book_id, gboolean ignore_lock, gboolean create, gboolean force) { GncDbiBackend* be = (GncDbiBackend*)qbe; const char* msg = nullptr; gboolean file_exists; PairVec options; g_return_if_fail (qbe != nullptr); g_return_if_fail (session != nullptr); g_return_if_fail (book_id != nullptr); ENTER (" "); /* Remove uri type if present */ auto path = gnc_uri_get_path (book_id); std::string filepath{path}; g_free(path); GFileTest ftest = static_cast<decltype (ftest)> ( G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS) ; file_exists = g_file_test (filepath.c_str(), ftest); if (!create && !file_exists) { qof_backend_set_error (qbe, ERR_FILEIO_FILE_NOT_FOUND); qof_backend_set_message (qbe, "Sqlite3 file %s not found", filepath.c_str()); PWARN ("Sqlite3 file %s not found", filepath.c_str()); LEAVE("Error"); return; } if (create && !force && file_exists) { qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS); msg = "Might clobber, no force"; PWARN ("%s", msg); LEAVE("Error"); return; } be->connect(nullptr); /* dbi-sqlite3 documentation says that sqlite3 doesn't take a "host" option */ options.push_back(std::make_pair("host", "localhost")); auto dirname = g_path_get_dirname (filepath.c_str()); auto basename = g_path_get_basename (filepath.c_str()); options.push_back(std::make_pair("dbname", basename)); options.push_back(std::make_pair("sqlite3_dbdir", dirname)); if (basename != nullptr) g_free (basename); if (dirname != nullptr) g_free (dirname); UriStrings uri; auto conn = conn_setup<DbType::DBI_SQLITE>(qbe, options, uri); if (conn == nullptr) { LEAVE("Error"); return; } auto result = dbi_conn_connect (conn); if (result < 0) { dbi_conn_close(conn); PERR ("Unable to connect to %s: %d\n", book_id, result); qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL); LEAVE("Error"); return; } if (!conn_test_dbi_library(conn, qbe)) { if (create && !file_exists) { /* File didn't exist before, but it does now, and we don't want to * leave it lying around. */ dbi_conn_close (conn); conn = nullptr; g_unlink (filepath.c_str()); } dbi_conn_close(conn); LEAVE("Bad DBI Library"); return; } try { be->connect(new GncDbiSqlConnection(DbType::DBI_SQLITE, qbe, conn, ignore_lock)); } catch (std::runtime_error& err) { return; } /* We should now have a proper session set up. * Let's start logging */ xaccLogSetBaseName (filepath.c_str()); PINFO ("logpath=%s", filepath.c_str() ? filepath.c_str() : "(null)"); LEAVE (""); }