|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Copyright (C) 2010-2011 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
- //
- // 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 <cppdb/backend.h>
- #include <cppdb/utils.h>
- #include <cppdb/pool.h>
-
- #include <map>
- #include <list>
-
- namespace cppdb {
- namespace backend {
- //result
- struct result::data {};
- result::result() {}
- result::~result() {}
-
- //statement
- struct statement::data {};
-
- statement::statement() : cache_(0)
- {
- }
- statement::~statement()
- {
- }
- void statement::cache(statements_cache *c)
- {
- cache_ = c;
- }
-
- void statement::dispose(statement *p)
- {
- if(!p)
- return;
- statements_cache *cache = p->cache_;
- p->cache_ = 0;
- if(cache)
- cache->put(p);
- else
- delete p;
- }
-
-
- //statements cache//////////////
-
- struct statements_cache::data {
-
- data() :
- size(0),
- max_size(0)
- {
- }
-
- struct entry;
- typedef std::map<std::string,entry> statements_type;
- typedef std::list<statements_type::iterator> lru_type;
- struct entry {
- ref_ptr<statement> stat;
- lru_type::iterator lru_ptr;
- };
-
- statements_type statements;
- lru_type lru;
- size_t size;
- size_t max_size;
-
-
- void insert(ref_ptr<statement> st)
- {
- statements_type::iterator p;
- if((p=statements.find(st->sql_query()))!=statements.end()) {
- p->second.stat = st;
- lru.erase(p->second.lru_ptr);
- lru.push_front(p);
- p->second.lru_ptr = lru.begin();
- }
- else {
- if(size > 0 && size >= max_size) {
- statements.erase(lru.back());
- lru.pop_back();
- size--;
- }
- std::pair<statements_type::iterator,bool> ins =
- statements.insert(std::make_pair(st->sql_query(),entry()));
- p = ins.first;
- p->second.stat = st;
- lru.push_front(p);
- p->second.lru_ptr = lru.begin();
- size ++;
- }
- }
-
- ref_ptr<statement> fetch(std::string const &query)
- {
- ref_ptr<statement> st;
- statements_type::iterator p = statements.find(query);
- if(p==statements.end())
- return st;
- st=p->second.stat;
- lru.erase(p->second.lru_ptr);
- statements.erase(p);
- size --;
- return st;
- }
-
- void clear()
- {
- lru.clear();
- statements.clear();
- size=0;
- }
- }; // data
-
- statements_cache::statements_cache()
- {
- }
- void statements_cache::set_size(size_t n)
- {
- if(n!=0 && !active()) {
- d.reset(new data());
- d->max_size = n;
- }
- }
- void statements_cache::put(statement *p_in)
- {
- if(!active()) {
- delete p_in;
- }
- ref_ptr<statement> p(p_in);
- p->reset();
- d->insert(p);
- }
- ref_ptr<statement> statements_cache::fetch(std::string const &q)
- {
- if(!active())
- return 0;
- return d->fetch(q);
- }
- void statements_cache::clear()
- {
- d->clear();
- }
- statements_cache::~statements_cache()
- {
- }
-
- bool statements_cache::active()
- {
- return d.get()!=0;
- }
-
- //////////////
- //connection
- //////////////
-
- struct connection::data {
- typedef std::list<connection_specific_data *> conn_specific_type;
- conn_specific_type conn_specific;
- ~data()
- {
- for(conn_specific_type::iterator p=conn_specific.begin();p!=conn_specific.end();++p)
- delete *p;
- }
- };
- ref_ptr<statement> connection::prepare(std::string const &q)
- {
- if(default_is_prepared_)
- return get_prepared_statement(q);
- else
- return get_statement(q);
- }
-
- ref_ptr<statement> connection::get_statement(std::string const &q)
- {
- ref_ptr<statement> st = create_statement(q);
- return st;
- }
-
- ref_ptr<statement> connection::get_prepared_statement(std::string const &q)
- {
- ref_ptr<statement> st;
- if(!cache_.active()) {
- st = prepare_statement(q);
- return st;
- }
- st = cache_.fetch(q);
- if(!st)
- st = prepare_statement(q);
- st->cache(&cache_);
- return st;
- }
-
- ref_ptr<statement> connection::get_prepared_uncached_statement(std::string const &q)
- {
- ref_ptr<statement> st = prepare_statement(q);
- return st;
- }
-
- connection::connection(connection_info const &info) :
- d(new connection::data),
- pool_(0),
- once_called_(0),
- recyclable_(1)
- {
- int cache_size = info.get("@stmt_cache_size",64);
- if(cache_size > 0) {
- cache_.set_size(cache_size);
- }
- std::string def_is_prep = info.get("@use_prepared","on");
- if(def_is_prep == "on")
- default_is_prepared_ = 1;
- else if(def_is_prep == "off")
- default_is_prepared_ = 0;
- else
- throw cppdb_error("cppdb::backend::connection: @use_prepared should be either 'on' or 'off'");
- }
- connection::~connection()
- {
- }
-
- bool connection::once_called() const
- {
- return once_called_;
- }
- void connection::once_called(bool v)
- {
- once_called_ = v;
- }
- connection_specific_data *connection::connection_specific_get(std::type_info const &type) const
- {
- for(data::conn_specific_type::const_iterator p=d->conn_specific.begin();p!=d->conn_specific.end();++p) {
- if(typeid(**p) == type)
- return *p;
- }
- return 0;
- }
- connection_specific_data *connection::connection_specific_release(std::type_info const &type)
- {
- for(data::conn_specific_type::iterator p=d->conn_specific.begin();p!=d->conn_specific.end();++p) {
- if(typeid(**p) == type) {
- connection_specific_data *ptr = *p;
- d->conn_specific.erase(p);
- return ptr;
- }
- }
- return 0;
- }
- void connection::connection_specific_reset(std::type_info const &type,connection_specific_data *ptr)
- {
- std::auto_ptr<connection_specific_data> tmp(ptr);
- if(ptr && typeid(*ptr)!=type) {
- throw cppdb_error(
- std::string("cppdb::connection_specific::Inconsistent pointer type")
- + typeid(*ptr).name()
- + " and std::type_info reference:"
- + type.name()
- );
- }
- for(data::conn_specific_type::iterator p=d->conn_specific.begin();p!=d->conn_specific.end();++p) {
- if(typeid(**p) == type) {
- delete *p;
- if(ptr)
- *p = tmp.release();
- else
- d->conn_specific.erase(p);
- return;
- }
- }
- if(ptr) {
- d->conn_specific.push_back(0);
- d->conn_specific.back() = tmp.release();
- }
- }
-
- ref_ptr<pool> connection::get_pool()
- {
- return pool_;
- }
- void connection::set_pool(ref_ptr<pool> p)
- {
- pool_ = p;
- }
- void connection::set_driver(ref_ptr<loadable_driver> p)
- {
- driver_ = p;
- }
- void connection::clear_cache()
- {
- cache_.clear();
- }
-
- void connection::recyclable(bool opt)
- {
- recyclable_ = opt;
- }
-
- bool connection::recyclable()
- {
- return recyclable_;
- }
-
- void connection::dispose(connection *c)
- {
- if(!c)
- return;
- ref_ptr<pool> p = c->pool_;
- c->pool_ = 0;
- if(p && c->recyclable())
- p->put(c);
- else {
- c->clear_cache();
- // Make sure that driver would not be
- // destoryed destructor of connection exits
- ref_ptr<loadable_driver> driver = c->driver_;
- delete c;
- driver.reset();
- }
- }
-
- connection *driver::connect(connection_info const &cs)
- {
- return open(cs);
- }
- bool loadable_driver::in_use()
- {
- return use_count() > 1;
- }
- connection *loadable_driver::connect(connection_info const &cs)
- {
- connection *c = open(cs);
- c->set_driver(ref_ptr<loadable_driver>(this));
- return c;
- }
-
- static_driver::static_driver(connect_function_type c) : connect_(c)
- {
- }
- static_driver::~static_driver()
- {
- }
- bool static_driver::in_use()
- {
- return true;
- }
- backend::connection *static_driver::open(connection_info const &ci)
- {
- return connect_(ci);
- }
-
- } // backend
-
- struct connection_specific_data::data {};
-
- connection_specific_data::connection_specific_data()
- {
- }
- connection_specific_data::~connection_specific_data()
- {
- }
-
-
- } // cppdb
-
-
|