Annotation of parser3/src/sql/odbc/parser3odbc.C, revision 1.3

1.1       parser      1: /** @file
                      2:        Parser ODBC driver.
                      3: 
                      4:        Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)
                      5: 
                      6:        Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)
                      7: */
1.3     ! parser      8: static const char *RCSId="$Id: parser3odbc.C,v 1.2 2001/07/25 12:46:45 parser Exp $"; 
1.1       parser      9: 
                     10: #ifndef _MSC_VER
                     11: #      error compile ISAPI module with MSVC [no urge for now to make it autoconf-ed (PAF)]
                     12: #endif
                     13: 
                     14: #include <string.h>
                     15: #include <stdio.h>
                     16: #include <stdlib.h>
                     17: 
                     18: #include "pa_sql_driver.h"
                     19: 
                     20: #include <AFXDB.H>
                     21: 
                     22: #define MAX_STRING 0x400
                     23: 
                     24: #define snprintf _snprintf
                     25: #ifndef strncasecmp
                     26: #      define strncasecmp _strnicmp
                     27: #endif
                     28: 
                     29: static char *lsplit(char *string, char delim) {
                     30:     if(string) {
                     31:                char *v=strchr(string, delim);
                     32:                if(v) {
                     33:                        *v=0;
                     34:                        return v+1;
                     35:                }
                     36:     }
                     37:     return 0;
                     38: }
                     39: 
                     40: /**
                     41:        ODBC server driver
                     42: */
                     43: class ODBC_Driver : public SQL_Driver {
                     44: public:
                     45: 
                     46:        ODBC_Driver() : SQL_Driver() {
                     47:        }
                     48: 
                     49:        /// get api version
                     50:        int api_version() { return SQL_DRIVER_API_VERSION; }
                     51:        const char *initialize(const char *dlopen_file_spec) { return 0; }
                     52:        /**     connect
                     53:                @param used_only_in_connect_url
                     54:                        format: @b DSN=dsn;UID=user;PWD=password (ODBC connect string)
                     55:                        WARNING: must be used only to connect, for buffer doesn't live long
                     56:        */
                     57:        void connect(
                     58:                char *used_only_in_connect_url, 
                     59:                SQL_Driver_services& services, 
                     60:                void **connection ///< output: CDatabase *
                     61:                ) {
                     62:        //      _asm int 3;
                     63:                CDatabase *db;
                     64:                TRY {
                     65:                        db=new CDatabase();
                     66:                        db->OpenEx(used_only_in_connect_url, CDatabase::noOdbcDialog);
                     67:                        db->BeginTrans();
                     68:                } 
                     69:                CATCH_ALL (e) {
                     70:                        _throw(services, e);
                     71:                        db=0; // calm, compiler
                     72:                }
                     73:                END_CATCH_ALL
                     74: 
                     75:                *(CDatabase **)connection=db;
                     76:        }
1.3     ! parser     77:        void disconnect(void *connection) {
1.1       parser     78:                CDatabase *db=static_cast<CDatabase *>(connection);
                     79:                TRY
                     80:                        delete db;
                     81:                CATCH_ALL (e) {
1.3     ! parser     82:                        // nothing
1.1       parser     83:                }
                     84:                END_CATCH_ALL
                     85:        }
                     86:        void commit(SQL_Driver_services& services, void *connection) {
                     87:                CDatabase *db=static_cast<CDatabase *>(connection);
                     88:                TRY
                     89:                        db->CommitTrans();
                     90:                        db->BeginTrans();
                     91:                CATCH_ALL (e) {
                     92:                        _throw(services, e);
                     93:                }
                     94:                END_CATCH_ALL
                     95:        }
                     96:        void rollback(SQL_Driver_services& services, void *connection) {
                     97:                CDatabase *db=static_cast<CDatabase *>(connection);
                     98:                TRY
                     99:                        db->Rollback();
                    100:                        db->BeginTrans();
                    101:                CATCH_ALL (e) {
                    102:                        _throw(services, e);
                    103:                }
                    104:                END_CATCH_ALL
                    105:        }
                    106: 
                    107:        bool ping(SQL_Driver_services&, void *connection) {
                    108:                return true;
                    109:        }
                    110: 
                    111:        unsigned int quote(
                    112:                SQL_Driver_services&, void *connection,
                    113:                char *to, const char *from, unsigned int length) {
                    114:                /*
                    115:                        You must allocate the to buffer to be at least length*2+1 bytes long. 
                    116:                        (In the worse case, each character may need to be encoded as using two bytes, 
                    117:                        and you need room for the terminating null byte.)
                    118: 
                    119:                        it's already UNTAINT_TIMES_BIGGER
                    120:                */
1.2       parser    121:                // ' -> ''
                    122:                unsigned int result=length;
                    123:                while(length--) {
                    124:                        if(*from=='\'')
                    125:                                *to++='\'';
                    126:                        *to++=*from++;
                    127:                }
                    128:                return result;
1.1       parser    129:        }
                    130:        void query(
                    131:                SQL_Driver_services& services, void *connection, 
                    132:                const char *statement, unsigned long offset, unsigned long limit,
                    133:                SQL_Driver_query_event_handlers& handlers) {
                    134: 
                    135:                CDatabase *db=static_cast<CDatabase *>(connection);
                    136: 
                    137:                while(isspace(*statement)) 
                    138:                        statement++;
                    139:                
                    140:                TRY {
                    141:                        if(strncasecmp(statement, "select", 6)==0) {
                    142:                                CRecordset rs(db); 
                    143:                                rs.Open(
                    144:                                        CRecordset::forwardOnly, 
                    145:                                        statement,
                    146:                                        CRecordset::executeDirect   
                    147:                                        );
                    148: 
                    149:                                int column_count=rs.GetODBCFieldCount();
                    150:                                if(!column_count)
                    151:                                        services._throw("result contains no columns");
                    152: 
                    153:                                for(int i=0; i<column_count; i++){
                    154:                                        CString string;
                    155:                                        CODBCFieldInfo fieldinfo;
                    156:                                        rs.GetODBCFieldInfo(i, fieldinfo);
                    157:                                        size_t size=fieldinfo.m_strName.GetLength();
                    158:                                        void *ptr=0;
                    159:                                        if(size) {
                    160:                                                ptr=services.malloc(size);
                    161:                                                memcpy(ptr, (char *)LPCTSTR(fieldinfo.m_strName), size);
                    162:                                        }
                    163:                                        handlers.add_column(ptr, size);
                    164:                                }
                    165: 
                    166:                                handlers.before_rows();
                    167: 
                    168:                                unsigned long row=0;
                    169:                                while(!rs.IsEOF() && (!limit||(row<offset+limit))) {
                    170:                                        if(row>=offset) {
                    171:                                                handlers.add_row();
                    172:                                                for(int i=0; i<column_count; i++)                                               {
                    173:                                                        CString string;
                    174:                                                        rs.GetFieldValue(i, string);
                    175:                                                        size_t size=string.GetLength();
                    176:                                                        void *ptr=0;
                    177:                                                        if(size) {
                    178:                                                                ptr=services.malloc(size);
                    179:                                                                memcpy(ptr, (char *)LPCTSTR(string), size);
                    180:                                                        }
                    181:                                                        handlers.add_row_cell(ptr, size);
                    182:                                                }
                    183:                                        }
1.2       parser    184:                                        rs.MoveNext();  row++;
1.1       parser    185:                                }
                    186:                                
                    187:                                rs.Close();
                    188:                        } else {
1.2       parser    189:                                db->ExecuteSQL(statement);
1.1       parser    190:                        }
                    191:                } 
                    192:                CATCH_ALL (e) {
                    193:                        _throw(services, e);
                    194:                }
                    195:                END_CATCH_ALL
                    196:        }
                    197: 
                    198:        void _throw(SQL_Driver_services& services, CException *e) {
                    199:                char szCause[MAX_STRING]; szCause[0]=0;
                    200:                e->GetErrorMessage(szCause, MAX_STRING);
                    201:                char msg[MAX_STRING];
                    202:                snprintf(msg, MAX_STRING, "%s: %s",
                    203:                        e->GetRuntimeClass()->m_lpszClassName,
                    204:                        *szCause?szCause:"unknown");
                    205:                services._throw(msg);
                    206:        }
                    207: 
                    208: };
                    209: 
                    210: extern "C" SQL_Driver *create() {
                    211:        return new ODBC_Driver();
                    212: }

E-mail: