Annotation of parser3/src/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: parser3mysql.C,v 1.24 2001/06/29 08:35:26 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(SQL_Driver_services& services, void *connection) {
! 78: CDatabase *db=static_cast<CDatabase *>(connection);
! 79: TRY
! 80: delete db;
! 81: CATCH_ALL (e) {
! 82: _throw(services, e);
! 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: memcpy(to, from, length);//todo: ' -> ''
! 122: return length;
! 123: }
! 124: void query(
! 125: SQL_Driver_services& services, void *connection,
! 126: const char *statement, unsigned long offset, unsigned long limit,
! 127: SQL_Driver_query_event_handlers& handlers) {
! 128:
! 129: CDatabase *db=static_cast<CDatabase *>(connection);
! 130:
! 131: while(isspace(*statement))
! 132: statement++;
! 133:
! 134: TRY {
! 135: if(strncasecmp(statement, "select", 6)==0) {
! 136: CRecordset rs(db);
! 137: rs.Open(
! 138: CRecordset::forwardOnly,
! 139: statement,
! 140: CRecordset::executeDirect
! 141: );
! 142:
! 143: int column_count=rs.GetODBCFieldCount();
! 144: if(!column_count)
! 145: services._throw("result contains no columns");
! 146:
! 147: for(int i=0; i<column_count; i++){
! 148: CString string;
! 149: CODBCFieldInfo fieldinfo;
! 150: rs.GetODBCFieldInfo(i, fieldinfo);
! 151: size_t size=fieldinfo.m_strName.GetLength();
! 152: void *ptr=0;
! 153: if(size) {
! 154: ptr=services.malloc(size);
! 155: memcpy(ptr, (char *)LPCTSTR(fieldinfo.m_strName), size);
! 156: }
! 157: handlers.add_column(ptr, size);
! 158: }
! 159:
! 160: handlers.before_rows();
! 161:
! 162: unsigned long row=0;
! 163: while(!rs.IsEOF() && (!limit||(row<offset+limit))) {
! 164: if(row>=offset) {
! 165: handlers.add_row();
! 166: for(int i=0; i<column_count; i++) {
! 167: CString string;
! 168: rs.GetFieldValue(i, string);
! 169: size_t size=string.GetLength();
! 170: void *ptr=0;
! 171: if(size) {
! 172: ptr=services.malloc(size);
! 173: memcpy(ptr, (char *)LPCTSTR(string), size);
! 174: }
! 175: handlers.add_row_cell(ptr, size);
! 176: }
! 177: }
! 178: rs.MoveNext();
! 179: row++;
! 180: }
! 181:
! 182: rs.Close();
! 183: } else {
! 184: // empty result
! 185: }
! 186: }
! 187: CATCH_ALL (e) {
! 188: _throw(services, e);
! 189: }
! 190: END_CATCH_ALL
! 191: }
! 192:
! 193: void _throw(SQL_Driver_services& services, CException *e) {
! 194: char szCause[MAX_STRING]; szCause[0]=0;
! 195: e->GetErrorMessage(szCause, MAX_STRING);
! 196: char msg[MAX_STRING];
! 197: snprintf(msg, MAX_STRING, "%s: %s",
! 198: e->GetRuntimeClass()->m_lpszClassName,
! 199: *szCause?szCause:"unknown");
! 200: services._throw(msg);
! 201: }
! 202:
! 203: };
! 204:
! 205: extern "C" SQL_Driver *create() {
! 206: return new ODBC_Driver();
! 207: }
E-mail: