SOCI का परिचय - C ++ डेटाबेस एक्सेस लाइब्रेरी

प्रविष्टि


पुस्तकालय खुद काफी परिपक्व है - जीथब पर पहली रिलीज 2004 वर्ष तक वापस आती है। मुझे आश्चर्य हुआ जब एक खोज इंजन में हैबर ने मुझे इस अद्भुत पुस्तकालय का उल्लेख करने वाले लेखों का एक भी लिंक नहीं दिया।


उच्चारण: soci , पहले शब्दांश पर जोर देने के साथ।


एसओसीआई समाज के विशेषज्ञता के माध्यम से ORM :: type_conversion का समर्थन करता है।


डेटाबेस समर्थन (DB) (बैकेंड):



मैं मैनुअल का अनुवाद नहीं करूंगा या यहां उदाहरणों से कोड प्रदान नहीं करूंगा, लेकिन मैं इसे और अधिक दृश्य और रोचक बनाने के लिए अपने पिछले प्रोजेक्ट से कोड को अनुकूलित करने की कोशिश करूंगा (तालिका की संरचना में बदलाव, और अन्य सरलीकरण)।


स्थापना


हम मास्टर शाखा से कच्चे माल डाउनलोड करते हैं, उन्हें अनपैक करते हैं, और निर्देशिका के अंदर हम कमांड निष्पादित करते हैं:


खिड़कियों में


$ mkdir build && cd build && cmake -G "Visual Studio 15 2017 Win64" ../ && cmake --build .config रिलीज़

या अंतिम आदेश के बजाय, आप विजुअल स्टूडियो में परिणामी परियोजना को खोल सकते हैं और संकलित कर सकते हैं।
( विल्क ने कमांड लाइन पर सेमीक के साथ निर्माण के बारे में संकेत दिया)


निक्स पर


$ mkdir build && cd build && cmake ../ && sudo make install

समाज-9999.ebuild

यदि आप गेंटू लिनक्स के मालिक हैं या लिनक्स की गणना करते हैं और सिस्टम में SOCI के नवीनतम संस्करण को जीथब पर आधिकारिक रिपॉजिटरी से प्राप्त करना चाहते हैं, तो आप इस इंस्टॉलेशन फ़ाइल को /usr/portage/dev-db/soci/ सहेज सकते हैं, इस पर जाएं और कमांड चलाएं :


# सोसाइटी -9999.ebuild मैनिफ़ेस्ट && उभरना -va = dev-db / soci-9999

 # Copyright 1999-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 EAPI=6 if [[ ${PV} == *9999 ]] ; then SCM="git-r3" EGIT_REPO_URI="https://github.com/SOCI/${PN}.git" fi CMAKE_MIN_VERSION=2.6.0 inherit cmake-utils ${SCM} DESCRIPTION="Makes the illusion of embedding SQL queries in the regular C++ code" HOMEPAGE="http://soci.sourceforge.net/" if [[ ${PV} == *9999 ]] ; then SRC_URI="" KEYWORDS="~amd64 ~x86" else SRC_URI="https://github.com/SOCI/${PN}/archive/${PV}.tar.gz -> ${P}.tar.gz" KEYWORDS="amd64 x86" fi LICENSE="Boost-1.0" SLOT="0" IUSE="boost doc +empty firebird mysql odbc oracle postgres sqlite static-libs test" RDEPEND=" firebird? ( dev-db/firebird ) mysql? ( virtual/mysql ) odbc? ( dev-db/unixODBC ) oracle? ( dev-db/oracle-instantclient-basic ) postgres? ( dev-db/postgresql:= ) sqlite? ( dev-db/sqlite:3 ) " DEPEND="${RDEPEND} boost? ( dev-libs/boost ) " src_configure() { local mycmakeargs=( -DWITH_BOOST=$(usex boost) -DSOCI_EMPTY=$(usex empty) -DWITH_FIREBIRD=$(usex firebird) -DWITH_MYSQL=$(usex mysql) -DWITH_ODBC=$(usex odbc) -DWITH_ORACLE=$(usex oracle) -DWITH_POSTGRESQL=$(usex postgres) -DWITH_SQLITE3=$(usex sqlite) -DSOCI_STATIC=$(usex static-libs) -DSOCI_TESTS=$(usex test) -DWITH_DB2=OFF ) #use MYCMAKEARGS if you want enable IBM DB2 support cmake-utils_src_configure } src_install() { use doc && local HTML_DOCS=( doc/. ) cmake-utils_src_install } 

हम डेटाबेस के कनेक्शन के लिए एक पूल लिखते हैं


db_pool.hpp
 #ifndef db_pool_hpp #define db_pool_hpp //      GCC,       //    ,  deprecated auto_ptr (   4) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #include <soci/soci.h> #include <soci/connection-pool.h> #pragma GCC diagnostic pop #include <iostream> #include <string> class db_pool { soci::connection_pool* pool_; std::size_t pool_size_; public: db_pool():pool_(nullptr),pool_size_(0) {} ~db_pool() { close(); } soci::connection_pool* get_pool() { return pool_; } bool connect(const std::string& conn_str, std::size_t n = 5) { if (pool_ != nullptr) { close(); } int is_connected = 0; if (!(pool_ = new soci::connection_pool((pool_size_ = n)))) return false; try { soci::indicator ind; for (std::size_t _i = 0; _i < pool_size_; _i++) { soci::session& sql = pool_->at(_i); //        sql.open(conn_str); //     sql << "SELECT 1;", soci::into(is_connected, ind); if (!is_connected) break; else if (_i+1 < pool_size_) is_connected = 0; } } catch (std::exception const & e) { std::cerr << e.what() << std::endl; } if (!is_connected) close(); return (pool_ != nullptr); } void close () { if (pool_ != nullptr) { try { for (std::size_t _i = 0; _i < pool_size_; _i++) { soci::session& sql = pool_->at(_i); sql.close(); } delete pool_; pool_ = nullptr; } catch (std::exception const & e) { std::cerr << e.what() << std::endl; } pool_size_ = 0; } } }; #endif 

User_info वर्ग में तालिका संरचना को परिभाषित करें


user_info.hpp
 #ifndef user_info_hpp #define user_info_hpp #include "db_pool.hpp" #include <ctime> #include <vector> #include <regex> #include <numeric> #include <algorithm> #include <iomanip> //   -        template<typename T> static void extract_integers(const std::string& str, std::vector<T>& result ) { result.clear(); using re_iterator = std::regex_iterator<std::string::const_iterator>; using re_iterated = re_iterator::value_type; std::regex re("([\\+\\-]?\\d+)"); re_iterator rit(str.begin(), str.end(), re), rend; std::transform(rit, rend, std::back_inserter(result), [](const re_iterated& it){return std::stoi(it[1]); }); } template<typename T> static void split_integers(std::string& str, const std::vector<T>& arr) { str = "{"; if (arr.size()) { str += std::accumulate(arr.begin()+1, arr.end(), std::to_string(arr[0]), [](const std::string& a, T b){return a + ',' + std::to_string(b);}); } str += "}"; } //   `users' class user_info { public: int id; //   std::tm birthday; //   std::string firstname, lastname; //    std::vector<int> friends; //   user_info():id(0),birthday(0),firstname(),lastname(),friends() {} void print() { std::cout.imbue(std::locale("ru_RU.utf8")); std::cout << "id: " << id << std::endl; std::cout << "birthday: " << std::put_time(&birthday, "%c %Z") << std::endl; std::cout << "firstname: " << firstname << std::endl; std::cout << "lastname: " << lastname << std::endl; std::string arr_str; split_integers(arr_str, friends); std::cout << "friends: " << arr_str << std::endl; } void clear() { id = 0; firstname = lastname = ""; friends.clear(); } user_info& operator=(const user_info& rhs) { if (this != &rhs) { id = rhs.id; birthday = rhs.birthday; firstname = rhs.firstname; lastname = rhs.lastname; friends = rhs.friends; } return *this; } }; //     ,  SOCI   namespace soci { template<> struct type_conversion<user_info> { typedef values base_type; static void from_base(values const& v, indicator ind, user_info& p) { if (ind == i_null) return; try { p.id = v.get<int>("id", 0); p.birthday = v.get<std::tm>("birthday", {}); p.firstname = v.get<std::string>("firstname", {}); p.lastname = v.get<std::string>("lastname", {}); std::string arr_str = v.get<std::string>("friends", {}); extract_integers(arr_str, p.friends); } catch (std::exception const & e) { std::cerr << e.what() << std::endl; } } static void to_base(const user_info& p, values& v, indicator& ind) { try { v.set("id", p.id); v.set("birthday", p.birthday); v.set("firstname", p.firstname); v.set("lastname", p.lastname); std::string arr_str; split_integers(arr_str, p.friends); v.set("friends", arr_str); ind = i_ok; return; } catch (std::exception const & e) { std::cerr << e.what() << std::endl; } ind = i_null; } }; } #endif 

हमारे कोड का परीक्षण


test.cxx
 #ifndef test_cxx #define test_cxx #include "user_info.hpp" // g++ -std=c++11 test.cxx -o test -lsoci_core -lsoci_postgresql -lsoci_mysql && ./test int main() { db_pool db; /// \note  "postgresql"   ,         if (db.connect("postgresql://host='localhost' dbname='test' user='test' password='test'")) { try { soci::session sql(*db.get_pool()); //     std::string query_str = "CREATE TABLE IF NOT EXISTS users(id"; //     ,    -   id if (sql.get_backend_name() == "postgresql") query_str += " SERIAL "; else if (sql.get_backend_name() == "mysql") query_str += " INT AUTO_INCREMENT "; else query_str += " INT "; query_str += "NOT NULL PRIMARY KEY, birthday TIMESTAMP DEFAULT CURRENT_TIMESTAMP, firstname TEXT DEFAULT NULL, lastname TEXT DEFAULT NULL, friends TEXT DEFAULT NULL)"; //   sql << query_str; //   user_info info; std::time_t t = std::time(nullptr); info.birthday = *std::localtime(&t); info.firstname = "Dmitrij"; info.lastname = "Volin"; info.friends = {1,2,3,4,5,6,7,8,9}; sql << "INSERT INTO users(birthday, firstname, lastname, friends) VALUES(:birthday, :firstname, :lastname, :friends)", soci::use(info); t = std::time(nullptr); info.birthday = *std::localtime(&t); info.firstname = "Vasy"; info.lastname = "Pupkin"; info.friends = {11,22,33,44,55,66,77,88,99}; //       sql << "INSERT INTO users(birthday, firstname, lastname, friends) VALUES(:birthday, :firstname, :lastname, :friends)", soci::use(info); //   ,  : soci::i_ok, soci::i_null soci::indicator ind; //  MySQL  id   ,  AUTO_INCREMENT: // sql.get_backend()->get_last_insert_id(sql, "users", reinterpret_cast<long&>(id)); // //  PostgreSQL   id  ,    : // sql << "INSERT INTO users(birthday, firstname, lastname, friends) VALUES(:birthday, :firstname, :lastname, :friends) RETURNING id", soci::use(info), soci::into(id, ind); //      info.clear(); //       ,   `lastname' sql << "SELECT * FROM users WHERE lastname = :label LIMIT 1", soci::use(std::string("Volin"), "label"), soci::into(info, ind); if (ind == soci::i_null) std::cout << "      ..." << std::endl; else info.print(); std::cout << "++++++++++++++++++++++++++++++++++++++" << std::endl; //     soci::rowset<user_info> rs = (sql.prepare << "SELECT * FROM users"); for (auto it = rs.begin(); it != rs.end(); it++) { user_info& i = *it; i.print(); } //   sql << "DROP TABLE IF EXISTS users"; } catch (std::exception const & e) { std::cerr << e.what() << std::endl; } } return 0; } #endif 

निष्कर्ष


इस लेख में, हमने लाइब्रेरी की मुख्य विशेषताओं की जांच की।


अगले लेख में (यदि पाठकों की रुचि होगी), मैं बीएलओबी प्रकार के साथ काम करने के बारे में लिखूंगा - डेटाबेस में फ़ाइलों और चित्रों को संग्रहीत करने के लिए (पोस्टग्रैसेकल में ये ओआईडी फ़ील्ड हैं), साथ ही लेनदेन और तैयार अनुरोधों के बारे में।


संदर्भ


गीथूब पर एस.ओ.सी.आई.
SOCI होमपेज

Source: https://habr.com/ru/post/hi422881/


All Articles