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

E-mail: