Diff for /parser3/src/sql/mysql/Attic/parser3mysql.C between versions 1.1 and 1.15

version 1.1, 2001/04/04 10:54:33 version 1.15, 2001/04/26 15:09:08
Line 1 Line 1
 /** @file  /** @file
         Parser: MySQL driver.          Parser MySQL driver.
   
         Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)          Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)
   
         Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)          Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)
   
         $Id$          $Id$
 */  */
   
   #include "config_includes.h"
   
 #include "pa_sql_driver.h"  #include "pa_sql_driver.h"
   
   #define NO_CLIENT_LONG_LONG
   #include "mysql.h"
   #include "ltdl.h"
   
   #define MAX_STRING 0x400
   #define MAX_NUMBER 20
   
   #if _MSC_VER
   #       define snprintf _snprintf
   #endif
   
   static char *lsplit(char *string, char delim) {
       if(string) {
                   char *v=strchr(string, delim);
                   if(v) {
                           *v=0;
                           return v+1;
                   }
       }
       return 0;
   }
   
   /**
           MySQL server driver
           
           @todo figure out about memory for errors:
                   static=add multithread locks;
                   dynamic=who should free it up?
   */
 class MySQL_Driver : public SQL_Driver {  class MySQL_Driver : public SQL_Driver {
 public:  public:
   
         MySQL_Driver() : SQL_driver() {}          MySQL_Driver() : SQL_Driver() {
           }
   
         /// get api version          /// get api version
         int api_version() { return SQL_API_VERSION; }          int api_version() { return SQL_DRIVER_API_VERSION; }
           /// initialize driver by loading sql dynamic link library
           const char *initialize(const char *dlopen_file_spec) {
                   return dlink(dlopen_file_spec);
           }
         /// connect          /// connect
         virtual void *connect(const char *url) {           void connect(
                 return 0;                  char *url, /**< @b user:pass@host[:port]/database/charset 
                                      3.23.22b
                                      Currently the only option for character_set_name is cp1251_koi8 */
                   void **connection ///< output: MYSQL *
                   ) {
                   char *user=url;
                   char *host=lsplit(user, '@');
                   char *db=lsplit(host, '/');
                   char *pwd=lsplit(user, ':');
                   char *error_pos=0;
                   char *port_cstr=lsplit(host, ':');
                   int port=port_cstr?strtol(port_cstr, &error_pos, 0):0;
                   char *charset=lsplit(db, '/');
   
               MYSQL *mysql=mysql_init(NULL);
                   if(!mysql_real_connect(mysql, 
                           host, user, pwd, db, port?port:MYSQL_PORT, NULL, 0))
                           services->_throw(mysql_error(mysql));
   
                   if(charset) { 
                           // set charset
                           char statement[MAX_STRING]="set CHARACTER SET "; // cp1251_koi8
                           strncat(statement, charset, MAX_STRING);
                           
                           if(mysql_query(mysql, statement)) 
                                   services->_throw(mysql_error(mysql));
                           (*mysql_store_result)(mysql); // throw out the result [don't need but must call]
                   }
   
                   *(MYSQL **)connection=mysql;
         }          }
         /// disconnect          void disconnect(void *connection) {
         virtual void disconnect(void *info) {              mysql_close((MYSQL *)connection);
                 ;          }
           void commit(void *connection) {}
           void rollback(void *connection) {}
   
           bool ping(void *connection) {
                   return mysql_ping((MYSQL *)connection)==0;
         }          }
   
           unsigned int quote(void *connection,
                   char *to, const char *from, unsigned int length) {
                   /*
                           3.23.22b
                           You must allocate the to buffer to be at least length*2+1 bytes long. 
                           (In the worse case, each character may need to be encoded as using two bytes, 
                           and you need room for the terminating null byte.)
   
                           it's already UNTAINT_TIMES_BIGGER
                   */
                   return (*mysql_escape_string)(to, from, length);
           }
           void query(void *connection, 
                   const char *astatement, unsigned long offset, unsigned long limit,
                   unsigned int *column_count, Cell **columns, 
                   unsigned long *row_count, Cell ***rows) {
   
                   MYSQL *mysql=(MYSQL *)connection;
                   MYSQL_RES *res=NULL;
   
                   const char *statement;
                   if(offset || limit) {
                           size_t statement_size=strlen(astatement);
                           char *statement_limited=(char *)services->malloc(
                                   statement_size+MAX_NUMBER*2+8/* limit #,#*/+1);
                           char *cur=statement_limited;
                           memcpy(cur, astatement, statement_size); cur+=statement_size;
                           cur+=sprintf(cur, " limit ");
                           if(offset)
                                   cur+=snprintf(cur, MAX_NUMBER+1, "%u,", offset);
                           if(limit)
                                   cur+=snprintf(cur, MAX_NUMBER, "%u", limit);
                           statement=statement_limited;
                   } else
                           statement=astatement;
   
                   if(mysql_query(mysql, statement)) 
                           services->_throw(mysql_error(mysql));
                   if(!(res=mysql_store_result(mysql)) && mysql_field_count(mysql)) 
                           services->_throw(mysql_error(mysql));
                   if(!res) {
                           // empty result
                           *row_count=0;
                           *column_count=0;
                           return;
                   }
                   
                   *column_count=mysql_num_fields(res);
                   if(!*column_count) // old client
                           *column_count=mysql_field_count(mysql);
   
                   *columns=(Cell *)services->malloc(sizeof(Cell)*(*column_count));
   
                   *row_count=(unsigned long)mysql_num_rows(res);
                   *rows=(Cell **)services->malloc(sizeof(Cell *)*(*row_count));
                   
                   for(unsigned int i=0; i<(*column_count); i++){
                           MYSQL_FIELD *field=mysql_fetch_field(res);
                           size_t size=strlen(field->name);
                           (*columns)[i].size=size;
                           (*columns)[i].ptr=services->malloc(size);
                           memcpy((*columns)[i].ptr, field->name, size);
                   }
                   
                   for(unsigned long r=0; r<(*row_count); r++) 
                           if(MYSQL_ROW mysql_row=mysql_fetch_row(res)) { // never false..
                                   unsigned long *lengths=mysql_fetch_lengths(res);
                                   Cell *row=(Cell *)malloc(sizeof(Cell)*(*column_count));
                                   (*rows)[r]=row;
                                   for(unsigned int i=0; i<(*column_count); i++){
                                           size_t size=(size_t)lengths[i];
                                           row[i].size=size;
                                           row[i].ptr=services->malloc(size);
                                           memcpy(row[i].ptr, mysql_row[i], size);
                                   }
                   }
                   
                   mysql_free_result(res);
           }
   
   private: // mysql client library funcs
   
           typedef MYSQL* (STDCALL *t_mysql_init)(MYSQL *);        t_mysql_init mysql_init;
           
           typedef MYSQL_RES* (STDCALL *t_mysql_store_result)(MYSQL *); t_mysql_store_result mysql_store_result;
           
           typedef int             (STDCALL *t_mysql_query)(MYSQL *, const char *q); t_mysql_query mysql_query;
           
           typedef char * (STDCALL *t_mysql_error)(MYSQL *); t_mysql_error mysql_error;
           static char* STDCALL subst_mysql_error(MYSQL *mysql) { return (mysql)->net.last_error; }
   
           typedef MYSQL*          (STDCALL *t_mysql_real_connect)(MYSQL *, const char *host,
                                              const char *user,
                                              const char *passwd,
                                              const char *db,
                                              unsigned int port,
                                              const char *unix_socket,
                                              unsigned int clientflag); t_mysql_real_connect mysql_real_connect;
   
           typedef void            (STDCALL *t_mysql_close)(MYSQL *); t_mysql_close mysql_close;
           
           typedef int             (STDCALL *t_mysql_ping)(MYSQL *); t_mysql_ping mysql_ping;
           
           typedef unsigned long   (STDCALL *t_mysql_escape_string)(char *to,const char *from,
                                               unsigned long from_length); t_mysql_escape_string mysql_escape_string;
           
           typedef void            (STDCALL *t_mysql_free_result)(MYSQL_RES *result); t_mysql_free_result mysql_free_result;
           
           typedef unsigned long* (STDCALL *t_mysql_fetch_lengths)(MYSQL_RES *result); t_mysql_fetch_lengths mysql_fetch_lengths;
           
           typedef MYSQL_ROW       (STDCALL *t_mysql_fetch_row)(MYSQL_RES *result); t_mysql_fetch_row mysql_fetch_row;
           
           typedef MYSQL_FIELD*    (STDCALL *t_mysql_fetch_field)(MYSQL_RES *result); t_mysql_fetch_field mysql_fetch_field;
           
           typedef my_ulonglong (STDCALL *t_mysql_num_rows)(MYSQL_RES *); t_mysql_num_rows mysql_num_rows;
           static my_ulonglong STDCALL subst_mysql_num_rows(MYSQL_RES *res) { return res->row_count; }
           
           typedef unsigned int (STDCALL *t_mysql_num_fields)(MYSQL_RES *); t_mysql_num_fields mysql_num_fields;
           static unsigned int STDCALL subst_mysql_num_fields(MYSQL_RES *res) { return res->field_count; }
   
           typedef unsigned int (STDCALL *t_mysql_field_count)(MYSQL *); t_mysql_field_count mysql_field_count;
           static unsigned int STDCALL subst_mysql_field_count(MYSQL *mysql) { return mysql->field_count; }
   
   private: // mysql client library funcs linking
   
           const char *dlink(const char *dlopen_file_spec) {
           lt_dlhandle handle=lt_dlopen(dlopen_file_spec);
           if (!handle)
                           return "can not open the dynamic link module";
   
                   #define DSLINK(name, action) \
                           name=(t_##name)lt_dlsym(handle, #name); \
                                   if(!name) \
                                           action;
   
                   #define DLINK(name) DSLINK(name, return "function " #name " was not found")
                   #define SLINK(name) DSLINK(name, name=subst_##name)
                   
                   DLINK(mysql_init);
                   DLINK(mysql_store_result);
                   DLINK(mysql_query);
                   SLINK(mysql_error);
                   DLINK(mysql_real_connect);
                   DLINK(mysql_close);
                   DLINK(mysql_ping);
                   DLINK(mysql_escape_string);
                   DLINK(mysql_free_result);
                   DLINK(mysql_fetch_lengths);
                   DLINK(mysql_fetch_row);
                   DLINK(mysql_fetch_field);
                   SLINK(mysql_num_rows);
                   SLINK(mysql_num_fields);
                   SLINK(mysql_field_count);
                   return 0;
           }
   
 };  };
   
 extern "C" SQL_Driver *create() {  extern "C" SQL_Driver *create() {

Removed from v.1.1  
changed lines
  Added in v.1.15


E-mail: