/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2010-2011 Artyom Beilis (Tonkikh) // // Distributed under: // // the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // or (at your opinion) under: // // The MIT License // (See accompanying file MIT.txt or a copy at // http://www.opensource.org/licenses/mit-license.php) // /////////////////////////////////////////////////////////////////////////////// #define CPPDB_SOURCE #include #include #include #include #include #include #include extern "C" { #ifdef CPPDB_WITH_SQLITE3 cppdb::backend::connection *cppdb_sqlite3_get_connection(cppdb::connection_info const &cs); #endif #ifdef CPPDB_WITH_PQ cppdb::backend::connection *cppdb_postgresql_get_connection(cppdb::connection_info const &cs); #endif #ifdef CPPDB_WITH_ODBC cppdb::backend::connection *cppdb_odbc_get_connection(cppdb::connection_info const &cs); #endif #ifdef CPPDB_WITH_MYSQL cppdb::backend::connection *cppdb_mysql_get_connection(cppdb::connection_info const &cs); #endif } namespace cppdb { typedef backend::static_driver::connect_function_type connect_function_type; class so_driver : public backend::loadable_driver { public: so_driver(std::string const &name,std::vector const &so_list) : connect_(0) { std::string symbol_name = "cppdb_" + name + "_get_connection"; for(unsigned i=0;isafe_resolve(symbol_name,connect_); break; } } if(!so_ || !connect_) { throw cppdb_error("cppdb::driver failed to load driver " + name + " - no module found"); } } virtual backend::connection *open(connection_info const &ci) { return connect_(ci); } private: connect_function_type connect_; ref_ptr so_; }; backend::connection *driver_manager::connect(std::string const &str) { connection_info conn(str); return connect(conn); } backend::connection *driver_manager::connect(connection_info const &conn) { ref_ptr drv_ptr; drivers_type::iterator p; { // get driver mutex::guard lock(lock_); p=drivers_.find(conn.driver); if(p!=drivers_.end()) { drv_ptr = p->second; } else { drv_ptr = load_driver(conn); drivers_[conn.driver] = drv_ptr; } } return drv_ptr->connect(conn); } void driver_manager::collect_unused() { std::list > garbage; { mutex::guard lock(lock_); drivers_type::iterator p=drivers_.begin(),tmp; while(p!=drivers_.end()) { if(!p->second->in_use()) { garbage.push_back(p->second); tmp=p; ++p; drivers_.erase(tmp); } else { ++p; } } } garbage.clear(); } #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__CYGWIN__) # define CPPDB_LIBRARY_SUFFIX_V1 "-" CPPDB_SOVERSION CPPDB_LIBRARY_SUFFIX # define CPPDB_LIBRARY_SUFFIX_V2 CPPDB_LIBRARY_SUFFIX #elif defined(__APPLE__) # define CPPDB_LIBRARY_SUFFIX_V1 "." CPPDB_SOVERSION CPPDB_LIBRARY_SUFFIX # define CPPDB_LIBRARY_SUFFIX_V2 CPPDB_LIBRARY_SUFFIX #else # define CPPDB_LIBRARY_SUFFIX_V1 CPPDB_LIBRARY_SUFFIX "." CPPDB_SOVERSION # define CPPDB_LIBRARY_SUFFIX_V2 CPPDB_LIBRARY_SUFFIX #endif #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__) # define PATH_SEPARATOR ';' #else # define PATH_SEPARATOR ':' #endif ref_ptr driver_manager::load_driver(connection_info const &conn) { std::vector so_names; std::string module; std::vector search_paths = search_paths_; std::string mpath=conn.get("@modules_path"); if(!mpath.empty()) { size_t sep = mpath.find(PATH_SEPARATOR); search_paths.push_back(mpath.substr(0,sep)); while(sep drv=new so_driver(conn.driver,so_names); return drv; } void driver_manager::install_driver(std::string const &name,ref_ptr drv) { if(!drv) { throw cppdb_error("cppdb::driver_manager::install_driver: Can't install empty driver"); } mutex::guard lock(lock_); drivers_[name]=drv; } driver_manager::driver_manager() : no_default_directory_(false) { } // Borland erros on hidden destructors in classes without only static methods. #ifndef __BORLANDC__ driver_manager::~driver_manager() { } #endif void driver_manager::add_search_path(std::string const &p) { mutex::guard l(lock_); search_paths_.push_back(p); } void driver_manager::clear_search_paths() { mutex::guard l(lock_); search_paths_.clear(); } void driver_manager::use_default_search_path(bool v) { mutex::guard l(lock_); no_default_directory_ = !v; } driver_manager &driver_manager::instance() { static driver_manager instance; return instance; } namespace { struct initializer { initializer() { driver_manager::instance(); #ifdef CPPDB_WITH_SQLITE3 driver_manager::instance().install_driver( "sqlite3",new backend::static_driver(cppdb_sqlite3_get_connection) ); #endif #ifdef CPPDB_WITH_ODBC driver_manager::instance().install_driver( "odbc",new backend::static_driver(cppdb_odbc_get_connection) ); #endif #ifdef CPPDB_WITH_PQ driver_manager::instance().install_driver( "postgresql",new backend::static_driver(cppdb_postgresql_get_connection) ); #endif #ifdef CPPDB_WITH_MYSQL driver_manager::instance().install_driver( "mysql",new backend::static_driver(cppdb_mysql_get_connection) ); #endif } } init; } } // cppdb