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

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: */
        !             8: static const char *RCSId="$Id: parser3odbc.C,v 1.5 2001/09/05 09:22:45 parser Exp $"; 
        !             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:        }
        !            77:        void disconnect(void *connection) {
        !            78:                CDatabase *db=static_cast<CDatabase *>(connection);
        !            79:                TRY
        !            80:                        delete db;
        !            81:                CATCH_ALL (e) {
        !            82:                        // nothing
        !            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:                */
        !           121:                // ' -> ''
        !           122:                unsigned int result=length;
        !           123:                while(length--) {
        !           124:                        if(*from=='\'')
        !           125:                                *to++='\'';
        !           126:                        *to++=*from++;
        !           127:                }
        !           128:                return result;
        !           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:                                        }
        !           184:                                        rs.MoveNext();  row++;
        !           185:                                }
        !           186:                                
        !           187:                                rs.Close();
        !           188:                        } else {
        !           189:                                db->ExecuteSQL(statement);
        !           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 *SQL_DRIVER_CREATE() {
        !           211:        return new ODBC_Driver();
        !           212: }

E-mail: