Warning, file /sdk/codevis/thirdparty/soci/src/core/session.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #define SOCI_SOURCE
0009 #include "soci/session.h"
0010 #include "soci/connection-parameters.h"
0011 #include "soci/connection-pool.h"
0012 #include "soci/soci-backend.h"
0013 #include "soci/query_transformation.h"
0014 
0015 using namespace soci;
0016 using namespace soci::details;
0017 
0018 namespace // anonymous
0019 {
0020 
0021 void ensureConnected(session_backend * backEnd)
0022 {
0023     if (backEnd == NULL)
0024     {
0025         throw soci_error("Session is not connected.");
0026     }
0027 }
0028 
0029 // Standard logger class used by default.
0030 class standard_logger_impl : public logger_impl
0031 {
0032 public:
0033     standard_logger_impl()
0034     {
0035         logStream_ = NULL;
0036     }
0037 
0038     virtual void start_query(std::string const & query)
0039     {
0040         if (logStream_ != NULL)
0041         {
0042             *logStream_ << query << '\n';
0043         }
0044 
0045         lastQuery_ = query;
0046     }
0047 
0048     virtual void set_stream(std::ostream * s)
0049     {
0050         logStream_ = s;
0051     }
0052 
0053     virtual std::ostream * get_stream() const
0054     {
0055         return logStream_;
0056     }
0057 
0058     virtual std::string get_last_query() const
0059     {
0060         return lastQuery_;
0061     }
0062 
0063 private:
0064     virtual logger_impl* do_clone() const
0065     {
0066         return new standard_logger_impl;
0067     }
0068 
0069     std::ostream * logStream_;
0070     std::string lastQuery_;
0071 };
0072 
0073 } // namespace anonymous
0074 
0075 session::session()
0076     : once(this), prepare(this),
0077       logger_(new standard_logger_impl),
0078       uppercaseColumnNames_(false), backEnd_(NULL),
0079       isFromPool_(false), pool_(NULL)
0080 {
0081 }
0082 
0083 session::session(connection_parameters const & parameters)
0084     : once(this), prepare(this),
0085       logger_(new standard_logger_impl),
0086       lastConnectParameters_(parameters),
0087       uppercaseColumnNames_(false), backEnd_(NULL),
0088       isFromPool_(false), pool_(NULL)
0089 {
0090     open(lastConnectParameters_);
0091 }
0092 
0093 session::session(backend_factory const & factory,
0094     std::string const & connectString)
0095     : once(this), prepare(this),
0096     logger_(new standard_logger_impl),
0097       lastConnectParameters_(factory, connectString),
0098       uppercaseColumnNames_(false), backEnd_(NULL),
0099       isFromPool_(false), pool_(NULL)
0100 {
0101     open(lastConnectParameters_);
0102 }
0103 
0104 session::session(std::string const & backendName,
0105     std::string const & connectString)
0106     : once(this), prepare(this),
0107       logger_(new standard_logger_impl),
0108       lastConnectParameters_(backendName, connectString),
0109       uppercaseColumnNames_(false), backEnd_(NULL),
0110       isFromPool_(false), pool_(NULL)
0111 {
0112     open(lastConnectParameters_);
0113 }
0114 
0115 session::session(std::string const & connectString)
0116     : once(this), prepare(this),
0117       logger_(new standard_logger_impl),
0118       lastConnectParameters_(connectString),
0119       uppercaseColumnNames_(false), backEnd_(NULL),
0120       isFromPool_(false), pool_(NULL)
0121 {
0122     open(lastConnectParameters_);
0123 }
0124 
0125 session::session(connection_pool & pool)
0126     : logger_(new standard_logger_impl),
0127       isFromPool_(true), pool_(&pool)
0128 {
0129     poolPosition_ = pool.lease();
0130     session & pooledSession = pool.at(poolPosition_);
0131 
0132     once.set_session(&pooledSession);
0133     prepare.set_session(&pooledSession);
0134     backEnd_ = pooledSession.get_backend();
0135 }
0136 
0137 session::~session()
0138 {
0139     if (isFromPool_)
0140     {
0141         pool_->give_back(poolPosition_);
0142     }
0143     else
0144     {
0145         delete backEnd_;
0146     }
0147 }
0148 
0149 void session::open(connection_parameters const & parameters)
0150 {
0151     if (isFromPool_)
0152     {
0153         session & pooledSession = pool_->at(poolPosition_);
0154         pooledSession.open(parameters);
0155         backEnd_ = pooledSession.get_backend();
0156     }
0157     else
0158     {
0159         if (backEnd_ != NULL)
0160         {
0161             throw soci_error("Cannot open already connected session.");
0162         }
0163 
0164         backend_factory const * const factory = parameters.get_factory();
0165         if (factory == NULL)
0166         {
0167             throw soci_error("Cannot connect without a valid backend.");
0168         }
0169 
0170         backEnd_ = factory->make_session(parameters);
0171         lastConnectParameters_ = parameters;
0172     }
0173 }
0174 
0175 void session::open(backend_factory const & factory,
0176     std::string const & connectString)
0177 {
0178     open(connection_parameters(factory, connectString));
0179 }
0180 
0181 void session::open(std::string const & backendName,
0182     std::string const & connectString)
0183 {
0184     open(connection_parameters(backendName, connectString));
0185 }
0186 
0187 void session::open(std::string const & connectString)
0188 {
0189     open(connection_parameters(connectString));
0190 }
0191 
0192 void session::close()
0193 {
0194     if (isFromPool_)
0195     {
0196         pool_->at(poolPosition_).close();
0197         backEnd_ = NULL;
0198     }
0199     else
0200     {
0201         delete backEnd_;
0202         backEnd_ = NULL;
0203     }
0204 }
0205 
0206 void session::reconnect()
0207 {
0208     if (isFromPool_)
0209     {
0210         session & pooledSession = pool_->at(poolPosition_);
0211         pooledSession.reconnect();
0212         backEnd_ = pooledSession.get_backend();
0213     }
0214     else
0215     {
0216         backend_factory const * const lastFactory = lastConnectParameters_.get_factory();
0217         if (lastFactory == NULL)
0218         {
0219             throw soci_error("Cannot reconnect without previous connection.");
0220         }
0221 
0222         if (backEnd_ != NULL)
0223         {
0224             close();
0225         }
0226 
0227         // Indicate that we're reconnecting using a special parameter which can
0228         // be used by some backends (currently only ODBC) that interactive
0229         // prompts should be suppressed, as they would be unexpected during
0230         // reconnection, which may happen automatically and not in the result
0231         // of a user action.
0232         connection_parameters reconnectParameters(lastConnectParameters_);
0233         reconnectParameters.set_option(option_reconnect, option_true);
0234         backEnd_ = lastFactory->make_session(reconnectParameters);
0235     }
0236 }
0237 
0238 bool session::is_connected() const noexcept
0239 {
0240     try
0241     {
0242         return backEnd_ && backEnd_->is_connected();
0243     }
0244     catch (...)
0245     {
0246         // We must not throw from here, so just handle any exception as an
0247         // indication that the database connection is not available any longer.
0248         return false;
0249     }
0250 }
0251 
0252 void session::begin()
0253 {
0254     ensureConnected(backEnd_);
0255 
0256     backEnd_->begin();
0257 }
0258 
0259 void session::commit()
0260 {
0261     ensureConnected(backEnd_);
0262 
0263     backEnd_->commit();
0264 }
0265 
0266 void session::rollback()
0267 {
0268     ensureConnected(backEnd_);
0269 
0270     backEnd_->rollback();
0271 }
0272 
0273 std::ostringstream & session::get_query_stream()
0274 {
0275     if (isFromPool_)
0276     {
0277         return pool_->at(poolPosition_).get_query_stream();
0278     }
0279     else
0280     {
0281         return query_stream_;
0282     }
0283 }
0284 
0285 std::string session::get_query() const
0286 {
0287     if (isFromPool_)
0288     {
0289         return pool_->at(poolPosition_).get_query();
0290     }
0291     else
0292     {
0293         // preserve logical constness of get_query,
0294         // stream used as read-only here,
0295         session* pthis = const_cast<session*>(this);
0296 
0297         // sole place where any user-defined query transformation is applied
0298         if (query_transformation_)
0299         {
0300             return (*query_transformation_)(pthis->get_query_stream().str());
0301         }
0302         return pthis->get_query_stream().str();
0303     }
0304 }
0305 
0306 
0307 void session::set_query_transformation_(std::unique_ptr<details::query_transformation_function>&& qtf)
0308 {
0309     if (isFromPool_)
0310     {
0311         pool_->at(poolPosition_).set_query_transformation_(std::move(qtf));
0312     }
0313     else
0314     {
0315         query_transformation_= std::move(qtf);
0316     }
0317 }
0318 
0319 void session::set_logger(logger const & logger)
0320 {
0321     if (isFromPool_)
0322     {
0323         pool_->at(poolPosition_).set_logger(logger);
0324     }
0325     else
0326     {
0327         logger_ = logger;
0328     }
0329 }
0330 
0331 logger const & session::get_logger() const
0332 {
0333     if (isFromPool_)
0334     {
0335         return pool_->at(poolPosition_).get_logger();
0336     }
0337     else
0338     {
0339         return logger_;
0340     }
0341 }
0342 
0343 void session::set_log_stream(std::ostream * s)
0344 {
0345     if (isFromPool_)
0346     {
0347         pool_->at(poolPosition_).set_log_stream(s);
0348     }
0349     else
0350     {
0351         logger_.set_stream(s);
0352     }
0353 }
0354 
0355 std::ostream * session::get_log_stream() const
0356 {
0357     if (isFromPool_)
0358     {
0359         return pool_->at(poolPosition_).get_log_stream();
0360     }
0361     else
0362     {
0363         return logger_.get_stream();
0364     }
0365 }
0366 
0367 void session::log_query(std::string const & query)
0368 {
0369     if (isFromPool_)
0370     {
0371         pool_->at(poolPosition_).log_query(query);
0372     }
0373     else
0374     {
0375         logger_.start_query(query);
0376     }
0377 }
0378 
0379 std::string session::get_last_query() const
0380 {
0381     if (isFromPool_)
0382     {
0383         return pool_->at(poolPosition_).get_last_query();
0384     }
0385     else
0386     {
0387         return logger_.get_last_query();
0388     }
0389 }
0390 
0391 void session::set_got_data(bool gotData)
0392 {
0393     if (isFromPool_)
0394     {
0395         pool_->at(poolPosition_).set_got_data(gotData);
0396     }
0397     else
0398     {
0399         gotData_ = gotData;
0400     }
0401 }
0402 
0403 bool session::got_data() const
0404 {
0405     if (isFromPool_)
0406     {
0407         return pool_->at(poolPosition_).got_data();
0408     }
0409     else
0410     {
0411         return gotData_;
0412     }
0413 }
0414 
0415 void session::uppercase_column_names(bool forceToUpper)
0416 {
0417     if (isFromPool_)
0418     {
0419         pool_->at(poolPosition_).uppercase_column_names(forceToUpper);
0420     }
0421     else
0422     {
0423         uppercaseColumnNames_ = forceToUpper;
0424     }
0425 }
0426 
0427 bool session::get_uppercase_column_names() const
0428 {
0429     if (isFromPool_)
0430     {
0431         return pool_->at(poolPosition_).get_uppercase_column_names();
0432     }
0433     else
0434     {
0435         return uppercaseColumnNames_;
0436     }
0437 }
0438 
0439 bool session::get_next_sequence_value(std::string const & sequence, long long & value)
0440 {
0441     ensureConnected(backEnd_);
0442 
0443     return backEnd_->get_next_sequence_value(*this, sequence, value);
0444 }
0445 
0446 bool session::get_last_insert_id(std::string const & sequence, long long & value)
0447 {
0448     ensureConnected(backEnd_);
0449 
0450     return backEnd_->get_last_insert_id(*this, sequence, value);
0451 }
0452 
0453 details::once_temp_type session::get_table_names()
0454 {
0455     ensureConnected(backEnd_);
0456 
0457     return once << backEnd_->get_table_names_query();
0458 }
0459 
0460 details::prepare_temp_type session::prepare_table_names()
0461 {
0462     ensureConnected(backEnd_);
0463 
0464     return prepare << backEnd_->get_table_names_query();
0465 }
0466 
0467 details::prepare_temp_type session::prepare_column_descriptions(std::string & table_name)
0468 {
0469     ensureConnected(backEnd_);
0470 
0471     return prepare << backEnd_->get_column_descriptions_query(), use(table_name, "t");
0472 }
0473 
0474 ddl_type session::create_table(const std::string & tableName)
0475 {
0476     ddl_type ddl(*this);
0477 
0478     ddl.create_table(tableName);
0479     ddl.set_tail(")");
0480 
0481     return ddl;
0482 }
0483 
0484 void session::drop_table(const std::string & tableName)
0485 {
0486     ensureConnected(backEnd_);
0487 
0488     once << backEnd_->drop_table(tableName);
0489 }
0490 
0491 void session::truncate_table(const std::string & tableName)
0492 {
0493     ensureConnected(backEnd_);
0494 
0495     once << backEnd_->truncate_table(tableName);
0496 }
0497 
0498 ddl_type session::add_column(const std::string & tableName,
0499     const std::string & columnName, data_type dt,
0500     int precision, int scale)
0501 {
0502     ddl_type ddl(*this);
0503 
0504     ddl.add_column(tableName, columnName, dt, precision, scale);
0505 
0506     return ddl;
0507 }
0508 
0509 ddl_type session::alter_column(const std::string & tableName,
0510     const std::string & columnName, data_type dt,
0511     int precision, int scale)
0512 {
0513     ddl_type ddl(*this);
0514 
0515     ddl.alter_column(tableName, columnName, dt, precision, scale);
0516 
0517     return ddl;
0518 }
0519 
0520 ddl_type session::drop_column(const std::string & tableName,
0521     const std::string & columnName)
0522 {
0523     ddl_type ddl(*this);
0524 
0525     ddl.drop_column(tableName, columnName);
0526 
0527     return ddl;
0528 }
0529 
0530 std::string session::empty_blob()
0531 {
0532     ensureConnected(backEnd_);
0533 
0534     return backEnd_->empty_blob();
0535 }
0536 
0537 std::string session::nvl()
0538 {
0539     ensureConnected(backEnd_);
0540 
0541     return backEnd_->nvl();
0542 }
0543 
0544 std::string session::get_dummy_from_table() const
0545 {
0546     ensureConnected(backEnd_);
0547 
0548     return backEnd_->get_dummy_from_table();
0549 }
0550 
0551 std::string session::get_dummy_from_clause() const
0552 {
0553     std::string clause = get_dummy_from_table();
0554     if (!clause.empty())
0555         clause.insert(0, " from ");
0556 
0557     return clause;
0558 }
0559 
0560 void session::set_failover_callback(failover_callback & callback)
0561 {
0562     ensureConnected(backEnd_);
0563 
0564     backEnd_->set_failover_callback(callback, *this);
0565 }
0566 
0567 std::string session::get_backend_name() const
0568 {
0569     ensureConnected(backEnd_);
0570 
0571     return backEnd_->get_backend_name();
0572 }
0573 
0574 statement_backend * session::make_statement_backend()
0575 {
0576     ensureConnected(backEnd_);
0577 
0578     return backEnd_->make_statement_backend();
0579 }
0580 
0581 rowid_backend * session::make_rowid_backend()
0582 {
0583     ensureConnected(backEnd_);
0584 
0585     return backEnd_->make_rowid_backend();
0586 }
0587 
0588 blob_backend * session::make_blob_backend()
0589 {
0590     ensureConnected(backEnd_);
0591 
0592     return backEnd_->make_blob_backend();
0593 }