--- sql/odbc/parser3odbc.C 2004/01/26 15:13:13 1.18 +++ sql/odbc/parser3odbc.C 2004/07/28 14:23:32 1.24 @@ -5,7 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char *RCSId="$Id: parser3odbc.C,v 1.18 2004/01/26 15:13:13 paf Exp $"; +static const char *RCSId="$Id: parser3odbc.C,v 1.24 2004/07/28 14:23:32 paf Exp $"; #ifndef _MSC_VER # error compile ISAPI module with MSVC [no urge for now to make it autoconf-ed (PAF)] @@ -56,10 +56,16 @@ static char *lsplit(char *string, char d return 0; } +static void toupper_str(char *out, const char *in, size_t size) { + while(size--) + *out++=(char)toupper(*in++); +} + struct Connection { SQL_Driver_services* services; CDatabase* db; + const char* cstrClientCharset; }; /** @@ -75,23 +81,38 @@ public: int api_version() { return SQL_DRIVER_API_VERSION; } const char *initialize(char *dlopen_file_spec) { return 0; } /** connect - @param used_only_in_connect_url + @param url format: @b DSN=dsn;UID=user;PWD=password (ODBC connect string) WARNING: must be used only to connect, for buffer doesn't live long */ void connect( - char *used_only_in_connect_url, + char *url, SQL_Driver_services& services, void **connection_ref ///< output: Connection* ) { - // _asm int 3; - Connection& connection=*(Connection *)::calloc(sizeof(Connection), 1); + Connection& connection=*(Connection *)services.malloc(sizeof(Connection)); *connection_ref=&connection; connection.services=&services; + connection.cstrClientCharset=0; + + if(const char* key_start=strstr(url, "ClientCharset=")) { + const char* value_start=key_start+14/*strlen("ClientCharset=")*/; + const char* value_end=strchr(value_start, ';'); + if(!value_end) + value_end=url+strlen(url); + + if(size_t ClientCharsetLength=value_end-value_start) { + char* cstrClientCharset=(char*)services.malloc_atomic(ClientCharsetLength+1); + toupper_str(cstrClientCharset, value_start, ClientCharsetLength); + cstrClientCharset[ClientCharsetLength]=0; + + connection.cstrClientCharset=cstrClientCharset; + } + } TRY { connection.db=new CDatabase(); - connection.db->OpenEx(used_only_in_connect_url, CDatabase::noOdbcDialog); + connection.db->OpenEx(url, CDatabase::noOdbcDialog); connection.db->BeginTrans(); } CATCH_ALL (e) { @@ -148,14 +169,28 @@ public: return result; } void query(void *aconnection, - const char *statement, unsigned long offset, unsigned long limit, + const char *statement, + size_t placeholders_count, Placeholder* placeholders, + unsigned long offset, unsigned long limit, SQL_Driver_query_event_handlers& handlers) { Connection& connection=*static_cast(aconnection); CDatabase *db=connection.db; SQL_Driver_services& services=*connection.services; - while(isspace(*statement)) + if(placeholders_count>0) + services._throw("bind variables not supported (yet)"); + + // transcode from $request:charset to connect-string?client_charset + if(const char* cstrClientCharset=connection.cstrClientCharset) { + size_t transcoded_statement_size; + services.transcode(statement, strlen(statement), + statement, transcoded_statement_size, + services.request_charset(), + cstrClientCharset); + } + + while(isspace((unsigned char)*statement)) statement++; TRY { @@ -207,13 +242,21 @@ public: CODBCFieldInfo fieldinfo; rs.GetODBCFieldInfo(i, fieldinfo); column_types[i]=fieldinfo.m_nSQLType; - size_t size=fieldinfo.m_strName.GetLength(); + size_t length=fieldinfo.m_strName.GetLength(); char *str=0; - if(size) { - str=(char*)services.malloc_atomic(size+1); - memcpy(str, (char *)LPCTSTR(fieldinfo.m_strName), size+1); + if(length) { + str=(char*)services.malloc_atomic(length+1); + memcpy(str, (char *)LPCTSTR(fieldinfo.m_strName), length+1); + + // transcode to $request:charset from connect-string?client_charset + if(const char* cstrClientCharset=connection.cstrClientCharset) { + services.transcode(str, length, + str, length, + cstrClientCharset, + services.request_charset()); + } } - CHECK(handlers.add_column(sql_error, str, size)); + CHECK(handlers.add_column(sql_error, str, length)); } CHECK(handlers.before_rows(sql_error)); @@ -225,7 +268,7 @@ public: if(row>=offset) { CHECK(handlers.add_row(sql_error)); for(int i=0; i