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