--- sql/mysql/parser3mysql.C 2009/04/08 11:13:00 1.35 +++ sql/mysql/parser3mysql.C 2012/06/06 14:45:14 1.41 @@ -1,21 +1,22 @@ /** @file Parser MySQL driver. - Copyright(c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) - 2001.07.30 using MySQL 3.23.22b + 2001-07-30 using MySQL 3.23.22b - 2001.11.06 numrows on "HP-UX istok1 B.11.00 A 9000/869 448594332 two-user license" + 2001-11-06 numrows on "HP-UX istok1 B.11.00 A 9000/869 448594332 two-user license" 3.23.42 & 4.0.0.alfa never worked, both subst & .sl version returned 0 */ -static const char *RCSId="$Id: parser3mysql.C,v 1.35 2009/04/08 11:13:00 misha Exp $"; #include "config_includes.h" #include "pa_sql_driver.h" +volatile const char * IDENT_PARSER3MYSQL_C="$Id: parser3mysql.C,v 1.41 2012/06/06 14:45:14 moko Exp $" IDENT_PA_SQL_DRIVER_H; + #define NO_CLIENT_LONG_LONG #include "mysql.h" #include "ltdl.h" @@ -29,14 +30,16 @@ static const char *RCSId="$Id: parser3my #endif // for mysql < 4.1 +#if !defined(CLIENT_MULTI_RESULTS) || !defined(CLIENT_MULTI_STATEMENTS) +# define OLD_MYSQL_CLIENT 1 +#endif + #ifndef CLIENT_MULTI_RESULTS -#define CLIENT_MULTI_RESULTS (1UL << 17) -#define OLD_MYSQL_CLIENT 1 +# define CLIENT_MULTI_RESULTS (1UL << 17) #endif + #ifndef CLIENT_MULTI_STATEMENTS -#define CLIENT_MULTI_STATEMENTS (1UL << 16) -#undef OLD_MYSQL_CLIENT -#define OLD_MYSQL_CLIENT 1 +# define CLIENT_MULTI_STATEMENTS (1UL << 16) #endif static char *lsplit(char *string, char delim){ @@ -71,6 +74,46 @@ static void toupper_str(char *out, const *out++=(char)toupper(*in++); } +inline static bool is_column_transcode_required(enum_field_types type) { + switch(type) { + case MYSQL_TYPE_NULL: + + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_BIT: + + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_TIMESTAMP: + + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + return false; + break; + } + return true; +} + +inline static const char* strdup(SQL_Driver_services& services, char* str, size_t length) { + char *strm=(char*)services.malloc_atomic(length+1); + memcpy(strm, str, length); + strm[length]=0; + return (const char*)strm; +} + struct Connection { SQL_Driver_services* services; @@ -178,6 +221,10 @@ public: if(atoi(value)) if(mysql_options(connection.handle, MYSQL_OPT_NAMED_PIPE, 0)!=0) services._throw(mysql_error(connection.handle)); + } else if(strcasecmp(key, "local_infile")==0){ + if(atoi(value)) + if(mysql_options(connection.handle, MYSQL_OPT_LOCAL_INFILE, 0)!=0) + services._throw(mysql_error(connection.handle)); } else if(strcasecmp(key, "autocommit")==0){ if(atoi(value)==0) connection.autocommit=false; @@ -219,7 +266,7 @@ public: } if(charset){ - char statement[MAX_STRING]="SET CHARACTER SET "; + char statement[MAX_STRING+1]="SET CHARACTER SET "; strncat(statement, charset, MAX_STRING); _exec(connection, statement); } @@ -251,16 +298,63 @@ public: return mysql_ping(connection.handle)==0; } - const char* quote(void *aconnection, const char *from, unsigned int length) { + // charset here is services.request_charset(), not connection.client_charset + // thus we can't use the sql server quoting support + const char* quote(void *aconnection, const char *str, unsigned int length) { + const char* from; + const char* from_end=str+length; + + size_t quoted=0; + + for(from=str; from(aconnection); - /* - 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.) - */ - char *result=(char*)connection.services->malloc_atomic(length*2+1); - mysql_escape_string(result, from, length); + char *result=(char*)connection.services->malloc_atomic(length + quoted + 1); + char *to = result; + + for(from=str; fromname); - char* strm=(char*)services.malloc_atomic(length+1); - memcpy(strm, field->name, length+1); - const char* str=strm; - - // transcode column name from ?ClientCharset to $request:charset - if(transcode_needed){ +#define DO_FETCH_FIELDS(transcode_column_name) { \ + MYSQL_FIELD *fields = mysql_fetch_fields(res); \ + for(size_t i=0; i