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