Annotation of parser3/src/sql/mysql/parser3mysql.C, revision 1.13.2.3

1.1       paf         1: /** @file
                      2:        Parser: MySQL driver.
                      3: 
1.7       paf         4:        Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)
1.1       paf         5: 
1.7       paf         6:        Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)
1.1       paf         7: 
1.13.2.3! paf         8:        $Id: parser3mysql.C,v 1.13.2.2 2001/04/17 07:55:25 paf Exp $
1.1       paf         9: */
                     10: 
1.13.2.1  paf        11: #include "config_includes.h"
1.4       paf        12: 
1.1       paf        13: #include "pa_sql_driver.h"
1.13.2.2  paf        14: 
                     15: #define NO_CLIENT_LONG_LONG
1.4       paf        16: #include "mysql.h"
1.13.2.3! paf        17: #include "ltdl.h"
1.1       paf        18: 
1.9       paf        19: #define MAX_STRING 0x400
1.11      paf        20: #define MAX_NUMBER 20
1.9       paf        21: 
1.11      paf        22: #if _MSC_VER
                     23: #      define snprintf _snprintf
                     24: #endif
                     25: 
                     26: static char *lsplit(char *string, char delim) {
1.4       paf        27:     if(string) {
                     28:                char *v=strchr(string, delim);
                     29:                if(v) {
                     30:                        *v=0;
                     31:                        return v+1;
                     32:                }
                     33:     }
                     34:     return 0;
                     35: }
                     36: 
1.6       paf        37: /**
                     38:        MySQL server driver
                     39:        
1.10      paf        40:        @todo figure out about memory for errors:
                     41:                static=add multithread locks;
                     42:                dynamic=who should free it up?
1.6       paf        43: */
1.1       paf        44: class MySQL_Driver : public SQL_Driver {
                     45: public:
                     46: 
1.4       paf        47:        MySQL_Driver() : SQL_Driver() {
1.3       paf        48:        }
1.1       paf        49: 
                     50:        /// get api version
1.6       paf        51:        int api_version() { return SQL_DRIVER_API_VERSION; }
1.13.2.3! paf        52:        /// initialize driver by loading sql dynamic link library
        !            53:        const char *initialize(const char *dlopen_file_spec) {
        !            54:                return dlink(dlopen_file_spec);
        !            55:        }
1.4       paf        56:        /// connect
1.6       paf        57:        void connect(
1.9       paf        58:                char *url, /**< @b user:pass@host[:port]/database/charset 
                     59:                                   3.23.22b
                     60:                                   Currently the only option for character_set_name is cp1251_koi8 */
1.6       paf        61:                void **connection ///< output: MYSQL *
1.5       paf        62:                ) {
1.4       paf        63:                char *user=url;
                     64:                char *host=lsplit(user, '@');
                     65:                char *db=lsplit(host, '/');
                     66:                char *pwd=lsplit(user, ':');
                     67:                char *error_pos=0;
                     68:                char *port_cstr=lsplit(host, ':');
                     69:                int port=port_cstr?strtol(port_cstr, &error_pos, 0):0;
1.9       paf        70:                char *charset=lsplit(db, '/');
1.4       paf        71: 
                     72:            MYSQL *mysql=mysql_init(NULL);
                     73:                if(!mysql_real_connect(mysql, 
                     74:                        host, user, pwd, db, port?port:MYSQL_PORT, NULL, 0))
1.11      paf        75:                        services->_throw(mysql_error(mysql));
1.4       paf        76: 
1.9       paf        77:                if(charset) { 
                     78:                        // set charset
                     79:                        char statement[MAX_STRING]="set CHARACTER SET "; // cp1251_koi8
                     80:                        strncat(statement, charset, MAX_STRING);
                     81:                        
                     82:                        if(mysql_query(mysql, statement)) 
1.11      paf        83:                                services->_throw(mysql_error(mysql));
1.13.2.3! paf        84:                        (*mysql_store_result)(mysql); // throw out the result [don't need but must call]
1.9       paf        85:                }
                     86: 
1.6       paf        87:                *(MYSQL **)connection=mysql;
1.1       paf        88:        }
1.6       paf        89:        void disconnect(void *connection) {
                     90:            mysql_close((MYSQL *)connection);
1.1       paf        91:        }
1.6       paf        92:        void commit(void *connection) {}
                     93:        void rollback(void *connection) {}
1.7       paf        94: 
1.8       paf        95:        bool ping(void *connection) {
                     96:                return mysql_ping((MYSQL *)connection)==0;
                     97:        }
                     98: 
1.9       paf        99:        unsigned int quote(void *connection,
                    100:                char *to, const char *from, unsigned int length) {
                    101:                /*
                    102:                        3.23.22b
                    103:                        You must allocate the to buffer to be at least length*2+1 bytes long. 
                    104:                        (In the worse case, each character may need to be encoded as using two bytes, 
                    105:                        and you need room for the terminating null byte.)
                    106: 
                    107:                        it's already UNTAINT_TIMES_BIGGER
                    108:                */
1.13.2.3! paf       109:                return (*mysql_escape_string)(to, from, length);
1.9       paf       110:        }
1.7       paf       111:        void query(void *connection, 
1.11      paf       112:                const char *astatement, unsigned long offset, unsigned long limit,
1.7       paf       113:                unsigned int *column_count, Cell **columns, 
                    114:                unsigned long *row_count, Cell ***rows) {
                    115: 
                    116:                MYSQL *mysql=(MYSQL *)connection;
                    117:                MYSQL_RES *res=NULL;
1.8       paf       118: 
1.11      paf       119:                const char *statement;
                    120:                if(offset || limit) {
                    121:                        size_t statement_size=strlen(astatement);
                    122:                        char *statement_limited=(char *)services->malloc(
                    123:                                statement_size+MAX_NUMBER*2+8/* limit #,#*/+1);
                    124:                        char *cur=statement_limited;
                    125:                        memcpy(cur, astatement, statement_size); cur+=statement_size;
                    126:                        cur+=sprintf(cur, " limit ");
                    127:                        if(offset)
1.13      paf       128:                                cur+=snprintf(cur, MAX_NUMBER+1, "%u,", offset);
1.11      paf       129:                        if(limit)
1.13      paf       130:                                cur+=snprintf(cur, MAX_NUMBER, "%u", limit);
1.11      paf       131:                        statement=statement_limited;
                    132:                } else
                    133:                        statement=astatement;
                    134: 
1.7       paf       135:                if(mysql_query(mysql, statement)) 
1.11      paf       136:                        services->_throw(mysql_error(mysql));
1.7       paf       137:                if(!(res=mysql_store_result(mysql)) && mysql_field_count(mysql)) 
1.11      paf       138:                        services->_throw(mysql_error(mysql));
1.7       paf       139:                if(!res) {
                    140:                        // empty result
                    141:                        *row_count=0;
                    142:                        *column_count=0;
                    143:                        return;
                    144:                }
                    145:                
                    146:                *column_count=mysql_num_fields(res);
1.11      paf       147:                *columns=(Cell *)services->malloc(sizeof(Cell)*(*column_count));
1.7       paf       148: 
                    149:                *row_count=(unsigned long)mysql_num_rows(res);
1.11      paf       150:                *rows=(Cell **)services->malloc(sizeof(Cell *)*(*row_count));
1.7       paf       151:                
                    152:                for(unsigned int i=0; i<(*column_count); i++){
                    153:                        MYSQL_FIELD *field=mysql_fetch_field(res);
                    154:                        size_t size=strlen(field->name);
                    155:                        (*columns)[i].size=size;
1.11      paf       156:                        (*columns)[i].ptr=services->malloc(size);
1.7       paf       157:                        memcpy((*columns)[i].ptr, field->name, size);
                    158:                }
                    159:                
                    160:                for(unsigned long r=0; r<(*row_count); r++) 
                    161:                        if(MYSQL_ROW mysql_row=mysql_fetch_row(res)) { // never false..
                    162:                                unsigned long *lengths=mysql_fetch_lengths(res);
                    163:                                Cell *row=(Cell *)malloc(sizeof(Cell)*(*column_count));
                    164:                                (*rows)[r]=row;
                    165:                                for(unsigned int i=0; i<(*column_count); i++){
                    166:                                        size_t size=(size_t)lengths[i];
                    167:                                        row[i].size=size;
1.11      paf       168:                                        row[i].ptr=services->malloc(size);
1.7       paf       169:                                        memcpy(row[i].ptr, mysql_row[i], size);
                    170:                                }
                    171:                }
                    172:                
                    173:                mysql_free_result(res);
                    174:        }
1.13.2.3! paf       175: 
        !           176: private: // mysql client library funcs
        !           177: 
        !           178: #ifndef STDCALL
        !           179: #      if !defined(WIN32)
        !           180: #              define STDCALL
        !           181: #      else
        !           182: #              define STDCALL __stdcall
        !           183: #      endif
        !           184: #endif
        !           185: 
        !           186:        typedef MYSQL* (STDCALL *t_mysql_init)(MYSQL *);        t_mysql_init mysql_init;
        !           187:        typedef MYSQL_RES* (STDCALL *t_mysql_store_result)(MYSQL *); t_mysql_store_result mysql_store_result;
        !           188:        typedef int             (STDCALL *t_mysql_query)(MYSQL *, const char *q); t_mysql_query mysql_query;
        !           189:        //typedef char * (*t_mysql_error)(MYSQL *); t_mysql_error mysql_error;
        !           190: #ifndef mysql_error
        !           191:        char* STDCALL mysql_error(MYSQL *mysql) {
        !           192:                return (mysql)->net.last_error;
        !           193:        }
        !           194: #endif
        !           195: 
        !           196:        typedef MYSQL*          (STDCALL *t_mysql_real_connect)(MYSQL *, const char *host,
        !           197:                                           const char *user,
        !           198:                                           const char *passwd,
        !           199:                                           const char *db,
        !           200:                                           unsigned int port,
        !           201:                                           const char *unix_socket,
        !           202:                                           unsigned int clientflag); t_mysql_real_connect mysql_real_connect;
        !           203: 
        !           204:        typedef void            (STDCALL *t_mysql_close)(MYSQL *); t_mysql_close mysql_close;
        !           205:        typedef int             (STDCALL *t_mysql_ping)(MYSQL *); t_mysql_ping mysql_ping;
        !           206:        typedef unsigned long   (STDCALL *t_mysql_escape_string)(char *to,const char *from,
        !           207:                                            unsigned long from_length); t_mysql_escape_string mysql_escape_string;
        !           208:        typedef void            (STDCALL *t_mysql_free_result)(MYSQL_RES *result); t_mysql_free_result mysql_free_result;
        !           209:        typedef unsigned long* (STDCALL *t_mysql_fetch_lengths)(MYSQL_RES *result); t_mysql_fetch_lengths mysql_fetch_lengths;
        !           210:        typedef MYSQL_ROW       (STDCALL *t_mysql_fetch_row)(MYSQL_RES *result); t_mysql_fetch_row mysql_fetch_row;
        !           211:        typedef MYSQL_FIELD*    (STDCALL *t_mysql_fetch_field)(MYSQL_RES *result); t_mysql_fetch_field mysql_fetch_field;
        !           212:        //typedef my_ulonglong (STDCALL *t_mysql_num_rows)(MYSQL_RES *); t_mysql_num_rows mysql_num_rows;
        !           213: #ifndef mysql_num_rows
        !           214:        my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res)     {
        !           215:                return res->row_count;
        !           216:        }
        !           217: #endif
        !           218:        //typedef unsigned int (STDCALL *t_mysql_num_fields)(MYSQL_RES *); t_mysql_num_fields mysql_num_fields;
        !           219: #ifndef mysql_num_fields
        !           220:        unsigned int STDCALL mysql_num_fields(MYSQL_RES *res) {
        !           221:                return res->field_count;
        !           222:        }
        !           223: #endif
        !           224: 
        !           225: //     typedef unsigned int (STDCALL *t_mysql_field_count)(MYSQL *); t_mysql_field_count mysql_field_count;
        !           226: #ifndef mysql_field_count
        !           227:        unsigned int STDCALL mysql_field_count(MYSQL *mysql) {
        !           228:                return mysql->field_count;
        !           229:        }
        !           230: #endif
        !           231: 
        !           232: private: // mysql client library funcs linking
        !           233: 
        !           234:        const char *dlink(const char *dlopen_file_spec) {
        !           235:         lt_dlhandle handle=lt_dlopen(dlopen_file_spec);
        !           236:         if (!handle)
        !           237:                        return "can not open the dynamic link module";
        !           238: 
        !           239:                #define DLINK(name) \
        !           240:                        name=(t_##name)lt_dlsym(handle, #name); \
        !           241:                        if(!name) \
        !           242:                                return "function " #name " was not found";
        !           243:                
        !           244:                DLINK(mysql_init);
        !           245:                DLINK(mysql_store_result);
        !           246:                DLINK(mysql_query);
        !           247:                //DLINK(mysql_error);
        !           248:                DLINK(mysql_real_connect);
        !           249:                DLINK(mysql_close);
        !           250:                DLINK(mysql_ping);
        !           251:                DLINK(mysql_escape_string);
        !           252:                DLINK(mysql_free_result);
        !           253:                DLINK(mysql_fetch_lengths);
        !           254:                DLINK(mysql_fetch_row);
        !           255:                DLINK(mysql_fetch_field);
        !           256: //             DLINK(mysql_num_rows);
        !           257: //             DLINK(mysql_num_fields);
        !           258: //             DLINK(mysql_field_count);
        !           259:                return 0;
        !           260:        }
        !           261: 
1.1       paf       262: };
                    263: 
                    264: extern "C" SQL_Driver *create() {
                    265:        return new MySQL_Driver();
                    266: }

E-mail: