--- parser3/src/include/pa_sql_connection.h 2002/02/08 07:27:45 1.22 +++ parser3/src/include/pa_sql_connection.h 2003/12/10 14:54:53 1.35 @@ -1,57 +1,119 @@ /** @file Parser: sql fconnection decl. - Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) - Author: Alexander Petrosyan (http://paf.design.ru) - - $Id: pa_sql_connection.h,v 1.22 2002/02/08 07:27:45 paf Exp $ + Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) */ #ifndef PA_SQL_CONNECTION_H #define PA_SQL_CONNECTION_H -#include "pa_pool.h" +static const char * const IDENT_SQL_CONNECTION_H="$Date: 2003/12/10 14:54:53 $"; + + #include "pa_sql_driver.h" #include "pa_sql_driver_manager.h" // defines /// @see SQL_Driver_services_impl::_throw -#define SQL_CONNECTION_SERVICED_FUNC_GUARDED(actions) \ - if(!fservices || !setjmp(fservices->mark)) { \ - actions; \ - } else \ - fservices->propagate_exception(); +#ifdef PA_WITH_SJLJ_EXCEPTIONS + #define SQL_CONNECTION_SERVICED_FUNC_GUARDED(actions) \ + use(); \ + actions +#else + #define SQL_CONNECTION_SERVICED_FUNC_GUARDED(actions) \ + use(); \ + if(!setjmp(fservices.mark)) { \ + actions; \ + } else \ + fservices.propagate_exception(); +#endif -/// SQL connection. handy wrapper around low level SQL_Driver -class SQL_Connection : public Pooled { +/// SQL_Driver_services Pooled implementation +class SQL_Driver_services_impl: public SQL_Driver_services { + const String* furl; + Exception fexception; +public: + SQL_Driver_services_impl(): furl(0) {} + void set_url(const String& aurl) { furl=&aurl;} + const String& url_without_login() const; + + override void *malloc(size_t size) { return pa_malloc(size); } + override void *malloc_atomic(size_t size) { return pa_malloc_atomic(size); } + override void *realloc(void *ptr, size_t size) { return pa_realloc(ptr, size); } + + /** + normally we can't 'throw' from dynamic library, so + the idea is to #1 jump to C++ some function to main body, where + every function stack frame has exception unwind information + and from there... #2 propagate_exception() + + but when parser configured --with-sjlj-exceptions + one can simply 'throw' from dynamic library. + [sad story: one can not longjump/throw due to some bug in gcc as of 3.2.1 version] + */ + override void _throw(const SQL_Error& aexception) { + // converting SQL_exception to parser Exception + // hiding passwords and addresses from accidental show [imagine user forgot @exception] +#ifdef PA_WITH_SJLJ_EXCEPTIONS + throw +#else + fexception= +#endif + Exception(aexception.type(), + &url_without_login(), + aexception.comment()); + +#ifndef PA_WITH_SJLJ_EXCEPTIONS + longjmp(mark, 1); +#endif + } + virtual void propagate_exception() { +#ifndef PA_WITH_SJLJ_EXCEPTIONS + throw fexception; +#endif + } +}; - friend class SQL_Connection_ptr; +/// SQL connection. handy wrapper around low level SQL_Driver +class SQL_Connection: public PA_Object { + const String& furl; + SQL_Driver& fdriver; + SQL_Driver_services_impl fservices; + void *fconnection; + time_t time_used; + bool marked_to_rollback; public: - SQL_Connection(Pool& pool, const String& aurl, SQL_Driver& adriver) : Pooled(pool), + SQL_Connection(const String& aurl, SQL_Driver& adriver): furl(aurl), fdriver(adriver), fconnection(0), - time_used(0), used(0), + time_used(0), marked_to_rollback(false) { } + + SQL_Driver_services_impl& services() { return fservices; } const String& get_url() { return furl; } - void set_services(SQL_Driver_services *aservices) { - fservices=aservices; + void set_url() { + fservices.set_url(furl); + } + void use() { + time_used=time(0); // they started to use at this time } bool expired(time_t older_dies) { - return !used && time_usedclose_connection(furl, *this); - } - -private: // connection usage methods - - void use() { - time_used=time(0); // they started to use at this time - used++; - } - void unuse() { - used--; - if(!used) - close(); + SQL_driver_manager.close_connection(furl, this); } -private: // connection usage data - - int used; - -private: - - const String& furl; - SQL_Driver& fdriver; - SQL_Driver_services *fservices; - void *fconnection; - time_t time_used; - bool marked_to_rollback; -}; - -/// Auto-object used to track SQL_Connection usage -class SQL_Connection_ptr { - SQL_Connection *fconnection; -public: - explicit SQL_Connection_ptr(SQL_Connection *aconnection) : fconnection(aconnection) { - fconnection->use(); - } - ~SQL_Connection_ptr() { - fconnection->unuse(); - } - SQL_Connection* operator->() { - return fconnection; - } - SQL_Connection* get() const { - return fconnection; - } - - // copying - SQL_Connection_ptr(const SQL_Connection_ptr& src) : fconnection(src.fconnection) { - fconnection->use(); - } - SQL_Connection_ptr& operator =(const SQL_Connection_ptr& src) { - // may do without this=src check - fconnection->unuse(); - fconnection=src.fconnection; - fconnection->use(); - - return *this; - } }; #endif