From 3a160a80c788d81e48acf19a2cf68f29cf125dae Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 25 Jan 2024 18:52:59 +0300 Subject: Turn libodb-mysql repository into package for muti-package repository --- libodb-mysql/odb/mysql/database.cxx | 357 ++++++++++++++++++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 libodb-mysql/odb/mysql/database.cxx (limited to 'libodb-mysql/odb/mysql/database.cxx') diff --git a/libodb-mysql/odb/mysql/database.cxx b/libodb-mysql/odb/mysql/database.cxx new file mode 100644 index 0000000..6c0f1d6 --- /dev/null +++ b/libodb-mysql/odb/mysql/database.cxx @@ -0,0 +1,357 @@ +// file : odb/mysql/database.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include // std::memset + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +namespace odb +{ + namespace mysql + { + using odb::details::transfer_ptr; + + database:: + ~database () + { + } + + database:: + database (const char* user, + const char* passwd, + const char* db, + const char* host, + unsigned int port, + const char* socket, + const char* charset, + unsigned long client_flags, + transfer_ptr factory) + : odb::database (id_mysql), + user_ (user ? user : ""), + passwd_str_ (passwd ? passwd : ""), + passwd_ (passwd ? passwd_str_.c_str () : 0), + db_ (db ? db : ""), + host_ (host ? host : ""), + port_ (port), + socket_str_ (socket ? socket : ""), + socket_ (socket ? socket_str_.c_str () : 0), + charset_ (charset == 0 ? "" : charset), + client_flags_ (client_flags), + factory_ (factory.transfer ()) + { + if (!factory_) + factory_.reset (new connection_pool_factory ()); + + factory_->database (*this); + } + + database:: + database (const string& user, + const string& passwd, + const string& db, + const string& host, + unsigned int port, + const string* socket, + const string& charset, + unsigned long client_flags, + transfer_ptr factory) + : odb::database (id_mysql), + user_ (user), + passwd_str_ (passwd), + passwd_ (passwd_str_.c_str ()), + db_ (db), + host_ (host), + port_ (port), + socket_str_ (socket ? *socket : ""), + socket_ (socket ? socket_str_.c_str () : 0), + charset_ (charset), + client_flags_ (client_flags), + factory_ (factory.transfer ()) + { + if (!factory_) + factory_.reset (new connection_pool_factory ()); + + factory_->database (*this); + } + + database:: + database (const string& user, + const string* passwd, + const string& db, + const string& host, + unsigned int port, + const string* socket, + const string& charset, + unsigned long client_flags, + transfer_ptr factory) + : odb::database (id_mysql), + user_ (user), + passwd_str_ (passwd ? *passwd : ""), + passwd_ (passwd ? passwd_str_.c_str () : 0), + db_ (db), + host_ (host), + port_ (port), + socket_str_ (socket ? *socket : ""), + socket_ (socket ? socket_str_.c_str () : 0), + charset_ (charset), + client_flags_ (client_flags), + factory_ (factory.transfer ()) + { + if (!factory_) + factory_.reset (new connection_pool_factory ()); + + factory_->database (*this); + } + + database:: + database (const string& user, + const string& passwd, + const string& db, + const string& host, + unsigned int port, + const string& socket, + const string& charset, + unsigned long client_flags, + transfer_ptr factory) + : odb::database (id_mysql), + user_ (user), + passwd_str_ (passwd), + passwd_ (passwd_str_.c_str ()), + db_ (db), + host_ (host), + port_ (port), + socket_str_ (socket), + socket_ (socket_str_.c_str ()), + charset_ (charset), + client_flags_ (client_flags), + factory_ (factory.transfer ()) + { + if (!factory_) + factory_.reset (new connection_pool_factory ()); + + factory_->database (*this); + } + + database:: + database (const string& user, + const string* passwd, + const string& db, + const string& host, + unsigned int port, + const string& socket, + const string& charset, + unsigned long client_flags, + transfer_ptr factory) + : odb::database (id_mysql), + user_ (user), + passwd_str_ (passwd ? *passwd : ""), + passwd_ (passwd ? passwd_str_.c_str () : 0), + db_ (db), + host_ (host), + port_ (port), + socket_str_ (socket), + socket_ (socket_str_.c_str ()), + charset_ (charset), + client_flags_ (client_flags), + factory_ (factory.transfer ()) + { + if (!factory_) + factory_.reset (new connection_pool_factory ()); + + factory_->database (*this); + } + + database:: + database (int& argc, + char* argv[], + bool erase, + const string& charset, + unsigned long client_flags, + transfer_ptr factory) + : odb::database (id_mysql), + passwd_ (0), + socket_ (0), + charset_ (charset), + client_flags_ (client_flags), + factory_ (factory.transfer ()) + { + using namespace details; + + try + { + cli::argv_file_scanner scan (argc, argv, "--options-file", erase); + options ops (scan, cli::unknown_mode::skip, cli::unknown_mode::skip); + + user_ = ops.user (); + + if (ops.password_specified ()) + { + passwd_str_ = ops.password (); + passwd_ = passwd_str_.c_str (); + } + + db_ = ops.database (); + host_ = ops.host (); + port_ = ops.port (); + + if (ops.socket_specified ()) + { + socket_str_ = ops.socket (); + socket_ = socket_str_.c_str (); + } + } + catch (const cli::exception& e) + { + ostringstream ostr; + ostr << e; + throw cli_exception (ostr.str ()); + } + + if (!factory_) + factory_.reset (new connection_pool_factory ()); + + factory_->database (*this); + } + + void database:: + print_usage (ostream& os) + { + details::options::print_usage (os); + } + + transaction_impl* database:: + begin () + { + return new transaction_impl (*this); + } + + odb::connection* database:: + connection_ () + { + connection_ptr c (factory_->connect ()); + return c.release (); + } + + const database::schema_version_info& database:: + load_schema_version (const string& name) const + { + schema_version_info& svi (schema_version_map_[name]); + + // Construct the SELECT statement text. + // + string text ("SELECT `version`, `migration` FROM "); + + if (!svi.version_table.empty ()) + text += svi.version_table; // Already quoted. + else if (!schema_version_table_.empty ()) + text += schema_version_table_; // Already quoted. + else + text += "`schema_version`"; + + text += " WHERE `name` = ?"; + + // Bind parameters and results. + // + unsigned long psize[1] = {static_cast (name.size ())}; + my_bool pnull[1] = {0}; + MYSQL_BIND pbind[1]; + binding param (pbind, 1); + + memset (pbind, 0, sizeof (pbind)); + + pbind[0].buffer_type = MYSQL_TYPE_STRING; + pbind[0].buffer = const_cast (name.c_str ()); + pbind[0].buffer_length = psize[0]; + pbind[0].length = &psize[0]; + pbind[0].is_null = &pnull[0]; + + param.version++; + + signed char migration; + my_bool rnull[2]; + MYSQL_BIND rbind[2]; + binding result (rbind, 2); + + memset (rbind, 0, sizeof (rbind)); + + rbind[0].buffer_type = MYSQL_TYPE_LONGLONG; + rbind[0].is_unsigned = 1; + rbind[0].buffer = &svi.version; + rbind[0].is_null = &rnull[0]; + + rbind[1].buffer_type = MYSQL_TYPE_TINY; + rbind[1].is_unsigned = 0; + rbind[1].buffer = &migration; + rbind[1].is_null = &rnull[1]; + + result.version++; + + // If we are not in transaction, MySQL will use an implicit one + // (i.e., autocommit mode), which suits us just fine. + // + connection_ptr cp; + if (!transaction::has_current ()) + cp = factory_->connect (); + + mysql::connection& c ( + cp != 0 + ? *cp + : transaction::current ().connection (const_cast (*this))); + + try + { + select_statement st (c, + text.c_str (), + false, // Don't process. + false, // Don't optimize. + param, + result, + false); + st.execute (); + auto_result ar (st); + + switch (st.fetch ()) + { + case select_statement::success: + { + svi.migration = migration != 0; + assert (st.fetch () == select_statement::no_data); + break; + } + case select_statement::no_data: + { + svi.version = 0; // No schema. + break; + } + case select_statement::truncated: + { + assert (false); + break; + } + } + } + catch (const database_exception& e) + { + // Detect the case where there is no version table. + // + if (e.error () == ER_NO_SUCH_TABLE) + svi.version = 0; // No schema. + else + throw; + } + + return svi; + } + } +} -- cgit v1.1