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