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 }