Annotation of sql/odbc/parser3odbc.C, revision 1.2

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.2     ! paf         8: static const char *RCSId="$Id: parser3odbc.C,v 1.1.1.1 2001/09/21 15:42:21 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>
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; }
                     52:        const char *initialize(const char *dlopen_file_spec) { return 0; }
                     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) {
                    115:                /*
                    116:                        You must allocate the to buffer to be at least length*2+1 bytes long. 
                    117:                        (In the worse case, each character may need to be encoded as using two bytes, 
                    118:                        and you need room for the terminating null byte.)
                    119: 
                    120:                        it's already UNTAINT_TIMES_BIGGER
                    121:                */
                    122:                // ' -> ''
                    123:                unsigned int result=length;
                    124:                while(length--) {
                    125:                        if(*from=='\'')
                    126:                                *to++='\'';
                    127:                        *to++=*from++;
                    128:                }
                    129:                return result;
                    130:        }
                    131:        void query(
                    132:                SQL_Driver_services& services, void *connection, 
                    133:                const char *statement, unsigned long offset, unsigned long limit,
                    134:                SQL_Driver_query_event_handlers& handlers) {
                    135: 
                    136:                CDatabase *db=static_cast<CDatabase *>(connection);
                    137: 
                    138:                while(isspace(*statement)) 
                    139:                        statement++;
                    140:                
                    141:                TRY {
                    142:                        if(strncasecmp(statement, "select", 6)==0) {
                    143:                                CRecordset rs(db); 
                    144:                                rs.Open(
                    145:                                        CRecordset::forwardOnly, 
                    146:                                        statement,
                    147:                                        CRecordset::executeDirect   
                    148:                                        );
                    149: 
                    150:                                int column_count=rs.GetODBCFieldCount();
                    151:                                if(!column_count)
                    152:                                        services._throw("result contains no columns");
                    153: 
                    154:                                for(int i=0; i<column_count; i++){
                    155:                                        CString string;
                    156:                                        CODBCFieldInfo fieldinfo;
                    157:                                        rs.GetODBCFieldInfo(i, fieldinfo);
                    158:                                        size_t size=fieldinfo.m_strName.GetLength();
                    159:                                        void *ptr=0;
                    160:                                        if(size) {
                    161:                                                ptr=services.malloc(size);
                    162:                                                memcpy(ptr, (char *)LPCTSTR(fieldinfo.m_strName), size);
                    163:                                        }
                    164:                                        handlers.add_column(ptr, size);
                    165:                                }
                    166: 
                    167:                                handlers.before_rows();
                    168: 
                    169:                                unsigned long row=0;
                    170:                                while(!rs.IsEOF() && (!limit||(row<offset+limit))) {
                    171:                                        if(row>=offset) {
                    172:                                                handlers.add_row();
                    173:                                                for(int i=0; i<column_count; i++)                                               {
                    174:                                                        CString string;
                    175:                                                        rs.GetFieldValue(i, string);
                    176:                                                        size_t size=string.GetLength();
                    177:                                                        void *ptr=0;
                    178:                                                        if(size) {
                    179:                                                                ptr=services.malloc(size);
                    180:                                                                memcpy(ptr, (char *)LPCTSTR(string), size);
                    181:                                                        }
                    182:                                                        handlers.add_row_cell(ptr, size);
                    183:                                                }
                    184:                                        }
                    185:                                        rs.MoveNext();  row++;
                    186:                                }
                    187:                                
                    188:                                rs.Close();
                    189:                        } else {
                    190:                                db->ExecuteSQL(statement);
                    191:                        }
                    192:                } 
                    193:                CATCH_ALL (e) {
                    194:                        _throw(services, e);
                    195:                }
                    196:                END_CATCH_ALL
                    197:        }
                    198: 
                    199:        void _throw(SQL_Driver_services& services, CException *e) {
                    200:                char szCause[MAX_STRING]; szCause[0]=0;
                    201:                e->GetErrorMessage(szCause, MAX_STRING);
                    202:                char msg[MAX_STRING];
                    203:                snprintf(msg, MAX_STRING, "%s: %s",
                    204:                        e->GetRuntimeClass()->m_lpszClassName,
                    205:                        *szCause?szCause:"unknown");
                    206:                services._throw(msg);
                    207:        }
                    208: 
                    209: };
                    210: 
                    211: extern "C" SQL_Driver *SQL_DRIVER_CREATE() {
                    212:        return new ODBC_Driver();
                    213: }

E-mail: