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: