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

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.11    ! paf         8:        $Id: parser3mysql.C,v 1.10 2001/04/05 16:30:43 paf Exp $
1.1       paf         9: */
                     10: 
1.4       paf        11: #include <stdlib.h>
1.10      paf        12: #include <string.h>
1.11    ! paf        13: #include <stdio.h>
1.4       paf        14: 
1.1       paf        15: #include "pa_sql_driver.h"
1.4       paf        16: #include "mysql.h"
1.1       paf        17: 
1.9       paf        18: #define MAX_STRING 0x400
1.11    ! paf        19: #define MAX_NUMBER 20
1.9       paf        20: 
1.11    ! paf        21: #if _MSC_VER
        !            22: #      define snprintf _snprintf
        !            23: #endif
        !            24: 
        !            25: static char *lsplit(char *string, char delim) {
1.4       paf        26:     if(string) {
                     27:                char *v=strchr(string, delim);
                     28:                if(v) {
                     29:                        *v=0;
                     30:                        return v+1;
                     31:                }
                     32:     }
                     33:     return 0;
                     34: }
                     35: 
1.6       paf        36: /**
                     37:        MySQL server driver
                     38:        
1.10      paf        39:        @todo figure out about memory for errors:
                     40:                static=add multithread locks;
                     41:                dynamic=who should free it up?
1.6       paf        42: */
1.1       paf        43: class MySQL_Driver : public SQL_Driver {
                     44: public:
                     45: 
1.4       paf        46:        MySQL_Driver() : SQL_Driver() {
1.3       paf        47:        }
1.1       paf        48: 
                     49:        /// get api version
1.6       paf        50:        int api_version() { return SQL_DRIVER_API_VERSION; }
1.4       paf        51:        /// connect
1.6       paf        52:        void connect(
1.9       paf        53:                char *url, /**< @b user:pass@host[:port]/database/charset 
                     54:                                   3.23.22b
                     55:                                   Currently the only option for character_set_name is cp1251_koi8 */
1.6       paf        56:                void **connection ///< output: MYSQL *
1.5       paf        57:                ) {
1.4       paf        58:                char *user=url;
                     59:                char *host=lsplit(user, '@');
                     60:                char *db=lsplit(host, '/');
                     61:                char *pwd=lsplit(user, ':');
                     62:                char *error_pos=0;
                     63:                char *port_cstr=lsplit(host, ':');
                     64:                int port=port_cstr?strtol(port_cstr, &error_pos, 0):0;
1.9       paf        65:                char *charset=lsplit(db, '/');
1.4       paf        66: 
                     67:            MYSQL *mysql=mysql_init(NULL);
                     68:                if(!mysql_real_connect(mysql, 
                     69:                        host, user, pwd, db, port?port:MYSQL_PORT, NULL, 0))
1.11    ! paf        70:                        services->_throw(mysql_error(mysql));
1.4       paf        71: 
1.9       paf        72:                if(charset) { 
                     73:                        // set charset
                     74:                        char statement[MAX_STRING]="set CHARACTER SET "; // cp1251_koi8
                     75:                        strncat(statement, charset, MAX_STRING);
                     76:                        
                     77:                        if(mysql_query(mysql, statement)) 
1.11    ! paf        78:                                services->_throw(mysql_error(mysql));
1.9       paf        79:                        mysql_store_result(mysql); // throw out the result [don't need but must call]
                     80:                }
                     81: 
1.6       paf        82:                *(MYSQL **)connection=mysql;
1.1       paf        83:        }
1.6       paf        84:        void disconnect(void *connection) {
                     85:            mysql_close((MYSQL *)connection);
1.1       paf        86:        }
1.6       paf        87:        void commit(void *connection) {}
                     88:        void rollback(void *connection) {}
1.7       paf        89: 
1.8       paf        90:        bool ping(void *connection) {
                     91:                return false;
                     92:                return mysql_ping((MYSQL *)connection)==0;
                     93:        }
                     94: 
1.9       paf        95:        unsigned int quote(void *connection,
                     96:                char *to, const char *from, unsigned int length) {
                     97:                /*
                     98:                        3.23.22b
                     99:                        You must allocate the to buffer to be at least length*2+1 bytes long. 
                    100:                        (In the worse case, each character may need to be encoded as using two bytes, 
                    101:                        and you need room for the terminating null byte.)
                    102: 
                    103:                        it's already UNTAINT_TIMES_BIGGER
                    104:                */
                    105:                return mysql_escape_string(to, from, length);
                    106:        }
1.7       paf       107:        void query(void *connection, 
1.11    ! paf       108:                const char *astatement, unsigned long offset, unsigned long limit,
1.7       paf       109:                unsigned int *column_count, Cell **columns, 
                    110:                unsigned long *row_count, Cell ***rows) {
                    111: 
                    112:                MYSQL *mysql=(MYSQL *)connection;
                    113:                MYSQL_RES *res=NULL;
1.8       paf       114: 
1.11    ! paf       115:                const char *statement;
        !           116:                if(offset || limit) {
        !           117:                        size_t statement_size=strlen(astatement);
        !           118:                        char *statement_limited=(char *)services->malloc(
        !           119:                                statement_size+MAX_NUMBER*2+8/* limit #,#*/+1);
        !           120:                        char *cur=statement_limited;
        !           121:                        memcpy(cur, astatement, statement_size); cur+=statement_size;
        !           122:                        cur+=sprintf(cur, " limit ");
        !           123:                        if(offset)
        !           124:                                cur+=snprintf(cur, MAX_NUMBER+1, "%lu,", offset);
        !           125:                        if(limit)
        !           126:                                cur+=snprintf(cur, MAX_NUMBER, "%lu", limit);
        !           127:                        statement=statement_limited;
        !           128:                } else
        !           129:                        statement=astatement;
        !           130: 
1.7       paf       131:                if(mysql_query(mysql, statement)) 
1.11    ! paf       132:                        services->_throw(mysql_error(mysql));
1.7       paf       133:                if(!(res=mysql_store_result(mysql)) && mysql_field_count(mysql)) 
1.11    ! paf       134:                        services->_throw(mysql_error(mysql));
1.7       paf       135:                if(!res) {
                    136:                        // empty result
                    137:                        *row_count=0;
                    138:                        *column_count=0;
                    139:                        return;
                    140:                }
                    141:                
                    142:                *column_count=mysql_num_fields(res);
1.11    ! paf       143:                *columns=(Cell *)services->malloc(sizeof(Cell)*(*column_count));
1.7       paf       144: 
                    145:                *row_count=(unsigned long)mysql_num_rows(res);
1.11    ! paf       146:                *rows=(Cell **)services->malloc(sizeof(Cell *)*(*row_count));
1.7       paf       147:                
                    148:                for(unsigned int i=0; i<(*column_count); i++){
                    149:                        MYSQL_FIELD *field=mysql_fetch_field(res);
                    150:                        size_t size=strlen(field->name);
                    151:                        (*columns)[i].size=size;
1.11    ! paf       152:                        (*columns)[i].ptr=services->malloc(size);
1.7       paf       153:                        memcpy((*columns)[i].ptr, field->name, size);
                    154:                }
                    155:                
                    156:                for(unsigned long r=0; r<(*row_count); r++) 
                    157:                        if(MYSQL_ROW mysql_row=mysql_fetch_row(res)) { // never false..
                    158:                                unsigned long *lengths=mysql_fetch_lengths(res);
                    159:                                Cell *row=(Cell *)malloc(sizeof(Cell)*(*column_count));
                    160:                                (*rows)[r]=row;
                    161:                                for(unsigned int i=0; i<(*column_count); i++){
                    162:                                        size_t size=(size_t)lengths[i];
                    163:                                        row[i].size=size;
1.11    ! paf       164:                                        row[i].ptr=services->malloc(size);
1.7       paf       165:                                        memcpy(row[i].ptr, mysql_row[i], size);
                    166:                                }
                    167:                }
                    168:                
                    169:                mysql_free_result(res);
                    170:        }
1.1       paf       171: };
                    172: 
                    173: extern "C" SQL_Driver *create() {
                    174:        return new MySQL_Driver();
                    175: }

E-mail: