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

1.1       paf         1: /** @file
1.15      paf         2:        Parser MySQL driver.
1.1       paf         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.27    ! parser      7: 
        !             8:        2001.07.30 using MySQL 3.23.22b
1.1       paf         9: */
1.27    ! parser     10: static const char *RCSId="$Id: parser3mysql.C,v 1.26 2001/07/23 13:59:52 parser Exp $"; 
1.1       paf        11: 
1.14      paf        12: #include "config_includes.h"
1.4       paf        13: 
1.1       paf        14: #include "pa_sql_driver.h"
1.14      paf        15: 
                     16: #define NO_CLIENT_LONG_LONG
1.4       paf        17: #include "mysql.h"
1.14      paf        18: #include "ltdl.h"
1.1       paf        19: 
1.9       paf        20: #define MAX_STRING 0x400
1.11      paf        21: #define MAX_NUMBER 20
1.9       paf        22: 
1.11      paf        23: #if _MSC_VER
                     24: #      define snprintf _snprintf
                     25: #endif
                     26: 
                     27: static char *lsplit(char *string, char delim) {
1.4       paf        28:     if(string) {
                     29:                char *v=strchr(string, delim);
                     30:                if(v) {
                     31:                        *v=0;
                     32:                        return v+1;
                     33:                }
                     34:     }
                     35:     return 0;
                     36: }
                     37: 
1.6       paf        38: /**
                     39:        MySQL server driver
                     40: */
1.1       paf        41: class MySQL_Driver : public SQL_Driver {
                     42: public:
                     43: 
1.4       paf        44:        MySQL_Driver() : SQL_Driver() {
1.3       paf        45:        }
1.1       paf        46: 
                     47:        /// get api version
1.6       paf        48:        int api_version() { return SQL_DRIVER_API_VERSION; }
1.14      paf        49:        /// initialize driver by loading sql dynamic link library
                     50:        const char *initialize(const char *dlopen_file_spec) {
1.26      parser     51:                return dlopen_file_spec?
                     52:                        dlink(dlopen_file_spec):"client library column is empty";
1.14      paf        53:        }
1.16      parser     54:        /**     connect
1.18      parser     55:                @param used_only_in_connect_url
1.21      parser     56:                        format: @b user:pass@host[:port]|[/unix/socket]/database/charset 
1.16      parser     57:                        3.23.22b
                     58:                        Currently the only option for @b character_set_name is cp1251_koi8.
                     59:                        WARNING: must be used only to connect, for buffer doesn't live long
                     60:        */
1.6       paf        61:        void connect(
1.18      parser     62:                char *used_only_in_connect_url, 
                     63:                SQL_Driver_services& services, 
1.6       paf        64:                void **connection ///< output: MYSQL *
1.5       paf        65:                ) {
1.18      parser     66:                char *user=used_only_in_connect_url;
1.20      parser     67:                char *s=lsplit(user, '@');
                     68:                char *host=0;
                     69:                char *unix_socket=0;
                     70:                if(s && s[0]=='[') { // unix socket
                     71:                        unix_socket=1+s;
                     72:                        s=lsplit(unix_socket, ']');
                     73:                } else { // IP
                     74:                        host=s;
                     75:                }
                     76:                char *db=lsplit(s, '/');
1.4       paf        77:                char *pwd=lsplit(user, ':');
                     78:                char *error_pos=0;
                     79:                char *port_cstr=lsplit(host, ':');
                     80:                int port=port_cstr?strtol(port_cstr, &error_pos, 0):0;
1.9       paf        81:                char *charset=lsplit(db, '/');
1.4       paf        82: 
                     83:            MYSQL *mysql=mysql_init(NULL);
                     84:                if(!mysql_real_connect(mysql, 
1.20      parser     85:                        host, user, pwd, db, port?port:MYSQL_PORT, unix_socket, 0))
1.18      parser     86:                        services._throw(mysql_error(mysql));
1.4       paf        87: 
1.9       paf        88:                if(charset) { 
                     89:                        // set charset
                     90:                        char statement[MAX_STRING]="set CHARACTER SET "; // cp1251_koi8
                     91:                        strncat(statement, charset, MAX_STRING);
                     92:                        
                     93:                        if(mysql_query(mysql, statement)) 
1.18      parser     94:                                services._throw(mysql_error(mysql));
1.14      paf        95:                        (*mysql_store_result)(mysql); // throw out the result [don't need but must call]
1.9       paf        96:                }
                     97: 
1.6       paf        98:                *(MYSQL **)connection=mysql;
1.1       paf        99:        }
1.18      parser    100:        void disconnect(SQL_Driver_services&, void *connection) {
1.6       paf       101:            mysql_close((MYSQL *)connection);
1.1       paf       102:        }
1.18      parser    103:        void commit(SQL_Driver_services&, void *) {}
                    104:        void rollback(SQL_Driver_services&, void *) {}
1.7       paf       105: 
1.18      parser    106:        bool ping(SQL_Driver_services&, void *connection) {
1.8       paf       107:                return mysql_ping((MYSQL *)connection)==0;
                    108:        }
                    109: 
1.18      parser    110:        unsigned int quote(
                    111:                SQL_Driver_services&, void *connection,
1.9       paf       112:                char *to, const char *from, unsigned int length) {
                    113:                /*
                    114:                        3.23.22b
                    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:                */
1.14      paf       121:                return (*mysql_escape_string)(to, from, length);
1.9       paf       122:        }
1.18      parser    123:        void query(
                    124:                SQL_Driver_services& services, void *connection, 
1.11      paf       125:                const char *astatement, unsigned long offset, unsigned long limit,
1.25      parser    126:                SQL_Driver_query_event_handlers& handlers) {
1.7       paf       127: 
                    128:                MYSQL *mysql=(MYSQL *)connection;
                    129:                MYSQL_RES *res=NULL;
1.8       paf       130: 
1.11      paf       131:                const char *statement;
                    132:                if(offset || limit) {
                    133:                        size_t statement_size=strlen(astatement);
1.18      parser    134:                        char *statement_limited=(char *)services.malloc(
1.11      paf       135:                                statement_size+MAX_NUMBER*2+8/* limit #,#*/+1);
                    136:                        char *cur=statement_limited;
                    137:                        memcpy(cur, astatement, statement_size); cur+=statement_size;
                    138:                        cur+=sprintf(cur, " limit ");
                    139:                        if(offset)
1.13      paf       140:                                cur+=snprintf(cur, MAX_NUMBER+1, "%u,", offset);
1.11      paf       141:                        if(limit)
1.13      paf       142:                                cur+=snprintf(cur, MAX_NUMBER, "%u", limit);
1.11      paf       143:                        statement=statement_limited;
                    144:                } else
                    145:                        statement=astatement;
                    146: 
1.7       paf       147:                if(mysql_query(mysql, statement)) 
1.18      parser    148:                        services._throw(mysql_error(mysql));
1.7       paf       149:                if(!(res=mysql_store_result(mysql)) && mysql_field_count(mysql)) 
1.18      parser    150:                        services._throw(mysql_error(mysql));
1.25      parser    151:                if(!res) // empty result: insert|delete|update|...
1.7       paf       152:                        return;
                    153:                
1.26      parser    154:                int column_count=mysql_num_fields(res);
1.25      parser    155:                if(!column_count) // old client
                    156:                        column_count=mysql_field_count(mysql);
1.14      paf       157: 
1.27    ! parser    158:                if(!column_count) {
        !           159:                        mysql_free_result(res);
1.19      parser    160:                        services._throw("result contains no columns");
1.27    ! parser    161:                }
1.19      parser    162: 
1.26      parser    163:                for(int i=0; i<column_count; i++){
1.7       paf       164:                        MYSQL_FIELD *field=mysql_fetch_field(res);
                    165:                        size_t size=strlen(field->name);
1.25      parser    166:                        void *ptr=services.malloc(size);
                    167:                        memcpy(ptr, field->name, size);
                    168:                        handlers.add_column(ptr, size);
1.7       paf       169:                }
1.25      parser    170: 
                    171:                handlers.before_rows();
1.7       paf       172:                
1.25      parser    173:                if(unsigned long row_count=(unsigned long)mysql_num_rows(res))
                    174:                        for(unsigned long r=0; r<row_count; r++) 
1.19      parser    175:                                if(MYSQL_ROW mysql_row=mysql_fetch_row(res)) { // never false..
1.25      parser    176:                                        handlers.add_row();
1.19      parser    177:                                        unsigned long *lengths=mysql_fetch_lengths(res);
1.26      parser    178:                                        for(int i=0; i<column_count; i++){
1.19      parser    179:                                                size_t size=(size_t)lengths[i];
1.25      parser    180:                                                void *ptr;
1.24      parser    181:                                                if(size) {
1.25      parser    182:                                                        ptr=services.malloc(size);
                    183:                                                        memcpy(ptr, mysql_row[i], size);
1.24      parser    184:                                                } else
1.25      parser    185:                                                        ptr=0;
                    186:                                                handlers.add_row_cell(ptr, size);
1.19      parser    187:                                        }
1.7       paf       188:                                }
1.19      parser    189: 
1.7       paf       190:                mysql_free_result(res);
                    191:        }
1.14      paf       192: 
                    193: private: // mysql client library funcs
                    194: 
                    195:        typedef MYSQL* (STDCALL *t_mysql_init)(MYSQL *);        t_mysql_init mysql_init;
                    196:        
                    197:        typedef MYSQL_RES* (STDCALL *t_mysql_store_result)(MYSQL *); t_mysql_store_result mysql_store_result;
                    198:        
                    199:        typedef int             (STDCALL *t_mysql_query)(MYSQL *, const char *q); t_mysql_query mysql_query;
                    200:        
                    201:        typedef char * (STDCALL *t_mysql_error)(MYSQL *); t_mysql_error mysql_error;
                    202:        static char* STDCALL subst_mysql_error(MYSQL *mysql) { return (mysql)->net.last_error; }
                    203: 
                    204:        typedef MYSQL*          (STDCALL *t_mysql_real_connect)(MYSQL *, const char *host,
                    205:                                           const char *user,
                    206:                                           const char *passwd,
                    207:                                           const char *db,
                    208:                                           unsigned int port,
                    209:                                           const char *unix_socket,
                    210:                                           unsigned int clientflag); t_mysql_real_connect mysql_real_connect;
                    211: 
                    212:        typedef void            (STDCALL *t_mysql_close)(MYSQL *); t_mysql_close mysql_close;
                    213:        
                    214:        typedef int             (STDCALL *t_mysql_ping)(MYSQL *); t_mysql_ping mysql_ping;
                    215:        
                    216:        typedef unsigned long   (STDCALL *t_mysql_escape_string)(char *to,const char *from,
                    217:                                            unsigned long from_length); t_mysql_escape_string mysql_escape_string;
                    218:        
                    219:        typedef void            (STDCALL *t_mysql_free_result)(MYSQL_RES *result); t_mysql_free_result mysql_free_result;
                    220:        
                    221:        typedef unsigned long* (STDCALL *t_mysql_fetch_lengths)(MYSQL_RES *result); t_mysql_fetch_lengths mysql_fetch_lengths;
                    222:        
                    223:        typedef MYSQL_ROW       (STDCALL *t_mysql_fetch_row)(MYSQL_RES *result); t_mysql_fetch_row mysql_fetch_row;
                    224:        
                    225:        typedef MYSQL_FIELD*    (STDCALL *t_mysql_fetch_field)(MYSQL_RES *result); t_mysql_fetch_field mysql_fetch_field;
                    226:        
                    227:        typedef my_ulonglong (STDCALL *t_mysql_num_rows)(MYSQL_RES *); t_mysql_num_rows mysql_num_rows;
                    228:        static my_ulonglong STDCALL subst_mysql_num_rows(MYSQL_RES *res) { return res->row_count; }
                    229:        
                    230:        typedef unsigned int (STDCALL *t_mysql_num_fields)(MYSQL_RES *); t_mysql_num_fields mysql_num_fields;
                    231:        static unsigned int STDCALL subst_mysql_num_fields(MYSQL_RES *res) { return res->field_count; }
                    232: 
                    233:        typedef unsigned int (STDCALL *t_mysql_field_count)(MYSQL *); t_mysql_field_count mysql_field_count;
                    234:        static unsigned int STDCALL subst_mysql_field_count(MYSQL *mysql) { return mysql->field_count; }
                    235: 
                    236: private: // mysql client library funcs linking
                    237: 
                    238:        const char *dlink(const char *dlopen_file_spec) {
                    239:         lt_dlhandle handle=lt_dlopen(dlopen_file_spec);
                    240:         if (!handle)
                    241:                        return "can not open the dynamic link module";
                    242: 
                    243:                #define DSLINK(name, action) \
                    244:                        name=(t_##name)lt_dlsym(handle, #name); \
                    245:                                if(!name) \
                    246:                                        action;
                    247: 
                    248:                #define DLINK(name) DSLINK(name, return "function " #name " was not found")
                    249:                #define SLINK(name) DSLINK(name, name=subst_##name)
                    250:                
                    251:                DLINK(mysql_init);
                    252:                DLINK(mysql_store_result);
                    253:                DLINK(mysql_query);
                    254:                SLINK(mysql_error);
                    255:                DLINK(mysql_real_connect);
                    256:                DLINK(mysql_close);
                    257:                DLINK(mysql_ping);
                    258:                DLINK(mysql_escape_string);
                    259:                DLINK(mysql_free_result);
                    260:                DLINK(mysql_fetch_lengths);
                    261:                DLINK(mysql_fetch_row);
                    262:                DLINK(mysql_fetch_field);
                    263:                SLINK(mysql_num_rows);
                    264:                SLINK(mysql_num_fields);
                    265:                SLINK(mysql_field_count);
                    266:                return 0;
                    267:        }
                    268: 
1.1       paf       269: };
                    270: 
                    271: extern "C" SQL_Driver *create() {
                    272:        return new MySQL_Driver();
                    273: }

E-mail: