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