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