Annotation of parser3/src/include/pa_sql_connection.h, revision 1.48

1.1       paf         1: /** @file
1.9       parser      2:        Parser: sql fconnection decl.
1.1       paf         3: 
1.48    ! moko        4:        Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com)
        !             5:        Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
1.1       paf         6: */
                      7: 
                      8: #ifndef PA_SQL_CONNECTION_H
                      9: #define PA_SQL_CONNECTION_H
1.25      paf        10: 
1.48    ! moko       11: #define IDENT_PA_SQL_CONNECTION_H "$Id: pa_sql_connection.h,v 1.47 2020/12/15 17:10:32 moko Exp $"
1.31      paf        12: 
1.1       paf        13: 
                     14: #include "pa_sql_driver.h"
1.4       paf        15: #include "pa_sql_driver_manager.h"
1.1       paf        16: 
1.15      paf        17: // defines
                     18: 
                     19: /// @see SQL_Driver_services_impl::_throw
1.28      paf        20: #ifdef PA_WITH_SJLJ_EXCEPTIONS
1.35      paf        21:        #define SQL_CONNECTION_SERVICED_FUNC_GUARDED(actions) \
                     22:                use(); \
                     23:                actions
1.28      paf        24: #else
                     25:        #define SQL_CONNECTION_SERVICED_FUNC_GUARDED(actions) \
1.35      paf        26:                use(); \
1.31      paf        27:                if(!setjmp(fservices.mark)) { \
1.28      paf        28:                        actions; \
                     29:                } else \
1.31      paf        30:                        fservices.propagate_exception();
                     31: #endif
                     32: 
                     33: /// SQL_Driver_services Pooled implementation
                     34: class SQL_Driver_services_impl: public SQL_Driver_services {
                     35:        const String* furl;
                     36:        Exception fexception;
1.37      paf        37:        const char* frequest_charset;
1.41      misha      38:        const char* fdocument_root;
1.31      paf        39: public:
1.41      misha      40:        SQL_Driver_services_impl(const char* arequest_charset, const char* adocument_root): furl(0), frequest_charset(arequest_charset), fdocument_root(adocument_root) {}
1.31      paf        41:        void set_url(const String& aurl) { furl=&aurl;}
1.34      paf        42:        const String& url_without_login() const;
1.31      paf        43: 
1.37      paf        44:        override void* malloc(size_t size) { return pa_malloc(size); }
                     45:        override void* malloc_atomic(size_t size) { return pa_malloc_atomic(size); }
                     46:        override void* realloc(void *ptr, size_t size) { return pa_realloc(ptr, size); }
                     47: 
                     48:        override const char* request_charset() { return frequest_charset; }
1.41      misha      49:        override const char* request_document_root() { return fdocument_root; }
                     50:        
1.37      paf        51:        override void transcode(const char* src, size_t src_length,
                     52:                const char*& dst, size_t& dst_length,
                     53:                const char* charset_from_name,
                     54:                const char* charset_to_name
                     55:                );
1.31      paf        56: 
                     57:        /**
                     58:                normally we can't 'throw' from dynamic library, so
                     59:                the idea is to #1 jump to C++ some function to main body, where
                     60:                every function stack frame has exception unwind information
                     61:                and from there... #2 propagate_exception()
                     62: 
                     63:         but when parser configured --with-sjlj-exceptions
                     64:                one can simply 'throw' from dynamic library.
                     65:                [sad story: one can not longjump/throw due to some bug in gcc as of 3.2.1 version]
                     66:        */
1.45      moko       67:        override void _throw(const SQL_Error& aexception) {
1.31      paf        68:                // converting SQL_exception to parser Exception
                     69:                // hiding passwords and addresses from accidental show [imagine user forgot @exception]
                     70: #ifdef PA_WITH_SJLJ_EXCEPTIONS
                     71:                throw
                     72: #else
                     73:                fexception=
1.28      paf        74: #endif
1.45      moko       75:                Exception(aexception.type() ? aexception.type() : "sql.connect", &url_without_login(), aexception.comment());
1.31      paf        76: 
                     77: #ifndef PA_WITH_SJLJ_EXCEPTIONS
                     78:                longjmp(mark, 1);
                     79: #endif
                     80:        }
1.45      moko       81: 
1.31      paf        82:        virtual void propagate_exception() {
                     83: #ifndef PA_WITH_SJLJ_EXCEPTIONS
                     84:                throw fexception;
                     85: #endif
                     86:        }
                     87: };
1.15      paf        88: 
1.14      parser     89: /// SQL connection. handy wrapper around low level SQL_Driver
1.31      paf        90: class SQL_Connection: public PA_Object {
                     91:        const String&  furl;
                     92:        SQL_Driver& fdriver;
                     93:        SQL_Driver_services_impl fservices;
                     94:        void *fconnection;
                     95:        time_t time_used;
1.21      paf        96: 
1.1       paf        97: public:
                     98: 
1.41      misha      99:        SQL_Connection(const String& aurl, SQL_Driver& adriver, const char* arequest_charset, const char* adocument_root):
1.1       paf       100:                furl(aurl),
1.10      parser    101:                fdriver(adriver),
1.41      misha     102:                fservices(arequest_charset, adocument_root),
1.10      parser    103:                fconnection(0),
1.37      paf       104:                time_used(0) {
1.9       parser    105:        }
1.34      paf       106: 
                    107:        SQL_Driver_services_impl& services() { return fservices; }
1.12      parser    108:        
1.18      paf       109:        const String& get_url() { return furl; }
1.12      parser    110: 
1.31      paf       111:        void set_url() {
                    112:                fservices.set_url(furl);
                    113:        }
                    114:        void use() {
                    115:                time_used=time(0); // they started to use at this time
1.1       paf       116:        }
1.10      parser    117:        bool expired(time_t older_dies) {
1.35      paf       118:                return time_used<older_dies;
1.1       paf       119:        }
1.21      paf       120:        time_t get_time_used() { return time_used; }
1.1       paf       121: 
1.10      parser    122:        bool connected() { return fconnection!=0; }
1.9       parser    123:        void connect(char *used_only_in_connect_url_cstr) { 
1.17      paf       124:                SQL_CONNECTION_SERVICED_FUNC_GUARDED(
1.31      paf       125:                        fdriver.connect(used_only_in_connect_url_cstr, fservices, &fconnection)
1.15      paf       126:                );
                    127:        }
                    128:        void disconnect() { 
1.16      paf       129:                fdriver.disconnect(fconnection); fconnection=0; 
1.15      paf       130:        }
                    131:        bool ping() { 
1.17      paf       132:                SQL_CONNECTION_SERVICED_FUNC_GUARDED(
1.37      paf       133:                        return fdriver.ping(fconnection)
1.15      paf       134:                );
1.46      moko      135:                return false; // never reached, warning war
1.9       parser    136:        }
1.31      paf       137:        const char* quote(const char* str, unsigned int length) {
1.17      paf       138:                SQL_CONNECTION_SERVICED_FUNC_GUARDED(
1.37      paf       139:                        return fdriver.quote(fconnection, str, length)
1.15      paf       140:                );
1.46      moko      141:                return NULL; // never reached, warning war
1.4       paf       142:        }
                    143: 
1.2       paf       144:        void query(
1.39      paf       145:                const char* statement, 
                    146:                size_t placeholders_count, SQL_Driver::Placeholder* placeholders,
                    147:                unsigned long offset, unsigned long limit,
1.27      paf       148:                SQL_Driver_query_event_handlers& handlers, 
                    149:                const String& source) {
                    150:                try {
                    151:                        SQL_CONNECTION_SERVICED_FUNC_GUARDED(
1.45      moko      152:                                fdriver.query(fconnection, statement, placeholders_count, placeholders, offset, limit, handlers)
                    153:                        );
1.27      paf       154:                } catch(const Exception& e) { // query problem
1.29      paf       155:                        if(strcmp(e.type(), "sql.connect")==0) { // if it is _throw exception, 
1.45      moko      156:                                // show query instead of connect string
                    157:                                throw Exception("sql.execute", &source, "%s", e.comment());
1.29      paf       158:                        } else
1.31      paf       159:                                rethrow;
1.27      paf       160:                }
1.2       paf       161:        }
                    162: 
1.21      paf       163:        void commit() { 
                    164:                SQL_CONNECTION_SERVICED_FUNC_GUARDED(
1.37      paf       165:                        fdriver.commit(fconnection) 
1.21      paf       166:                );
                    167:        }
                    168:        void rollback() { 
                    169:                SQL_CONNECTION_SERVICED_FUNC_GUARDED(
1.37      paf       170:                        fdriver.rollback(fconnection)
1.21      paf       171:                );
                    172:        }
                    173: 
                    174:        /// return to cache
                    175:        void close() {
1.36      paf       176:                SQL_driver_manager->close_connection(furl, this);
1.21      paf       177:        }
                    178: 
1.1       paf       179: };
                    180: 
                    181: #endif

E-mail: