--- sql/pgsql/parser3pgsql.C 2004/01/26 15:22:26 1.16 +++ sql/pgsql/parser3pgsql.C 2004/12/23 15:57:41 1.23 @@ -7,7 +7,7 @@ 2001.07.30 using PgSQL 7.1.2 */ -static const char *RCSId="$Id: parser3pgsql.C,v 1.16 2004/01/26 15:22:26 paf Exp $"; +static const char *RCSId="$Id: parser3pgsql.C,v 1.23 2004/12/23 15:57:41 paf Exp $"; #include "config_includes.h" @@ -58,10 +58,16 @@ static char *lsplit(char **string_ref, c return result; } +static void toupper_str(char *out, const char *in, size_t size) { + while(size--) + *out++=(char)toupper(*in++); +} + struct Connection { SQL_Driver_services* services; PGconn *conn; + const char* cstrClientCharset; }; /** @@ -89,15 +95,15 @@ public: #define PQclear_throwPQerror PQclear_throw(PQerrorMessage(connection.conn)) /** connect - @param used_only_in_connect_url + @param url format: @b user:pass@host[:port]|[local]/database */ void connect( - char *used_only_in_connect_url, + char *url, SQL_Driver_services& services, void **connection_ref ///< output: Connection* ) { - char *user=used_only_in_connect_url; + char *user=url; char *host=lsplit(user, '@'); char *db=lsplit(host, '/'); char *pwd=lsplit(user, ':'); @@ -105,9 +111,12 @@ public: char *options=lsplit(db, '?'); - Connection& connection=*(Connection *)::calloc(sizeof(Connection), 1); + char *cstrBackwardCompAskServerToTranscode=0; + + Connection& connection=*(Connection *)services.malloc(sizeof(Connection)); *connection_ref=&connection; connection.services=&services; + connection.cstrClientCharset=0; connection.conn=PQsetdbLogin( (host&&strcasecmp(host, "local")==0)?NULL/* local Unix domain socket */:host, port, NULL, NULL, db, user, pwd); @@ -118,15 +127,21 @@ public: char *charset=0; char *datestyle=0; + isDefaultTransaction = true; while(options) { if(char *key=lsplit(&options, '&')) { if(*key) { if(char *value=lsplit(key, '=')) { - if(strcasecmp(key, "charset")==0) { - charset=value; + if(strcmp(key, "ClientCharset" ) == 0) { + toupper_str(value, value, strlen(value)); + connection.cstrClientCharset=value; + } else if(strcasecmp(key, "charset")==0) { // left for backward compatibility, consider using ClientCharset + cstrBackwardCompAskServerToTranscode=value; } else if(strcasecmp(key, "datestyle")==0) { datestyle=value; + } else if(strcmp(key, "WithoutDefaultTransaction")==0) { + isDefaultTransaction = false; } else services._throw("unknown connect option" /*key*/); } else @@ -135,10 +150,14 @@ public: } } - if(charset) { + if(connection.cstrClientCharset && cstrBackwardCompAskServerToTranscode) + services._throw("use 'ClientCharset' option only, " + "'charset' option is obsolete and should not be used with new 'ClientCharset' option"); + + if(cstrBackwardCompAskServerToTranscode) { // set CLIENT_ENCODING char statement[MAX_STRING]="set CLIENT_ENCODING="; // win - strncat(statement, charset, MAX_STRING); + strncat(statement, cstrBackwardCompAskServerToTranscode, MAX_STRING); PGresult *res=PQexec(connection.conn, statement); if(!res) @@ -166,22 +185,28 @@ public: connection.conn=0; } void commit(void *aconnection) { - Connection& connection=*static_cast(aconnection); - - if(PGresult *res=PQexec(connection.conn, "COMMIT")) - PQclear(res); - else - throwPQerror; - begin_transaction(connection); + if(isDefaultTransaction) + { + Connection& connection=*static_cast(aconnection); + + if(PGresult *res=PQexec(connection.conn, "COMMIT")) + PQclear(res); + else + throwPQerror; + begin_transaction(connection); + } } void rollback(void *aconnection) { - Connection& connection=*static_cast(aconnection); - - if(PGresult *res=PQexec(connection.conn, "ROLLBACK")) - PQclear(res); - else - throwPQerror; - begin_transaction(connection); + if(isDefaultTransaction) + { + Connection& connection=*static_cast(aconnection); + + if(PGresult *res=PQexec(connection.conn, "ROLLBACK")) + PQclear(res); + else + throwPQerror; + begin_transaction(connection); + } } bool ping(void *aconnection) { @@ -212,13 +237,28 @@ public: return result; } void query(void *aconnection, - const char *astatement, unsigned long offset, unsigned long limit, + const char *astatement, + size_t placeholders_count, Placeholder* placeholders, + unsigned long offset, unsigned long limit, SQL_Driver_query_event_handlers& handlers) { // _asm int 3; Connection& connection=*static_cast(aconnection); + const char* cstrClientCharset=connection.cstrClientCharset; SQL_Driver_services& services=*connection.services; PGconn *conn=connection.conn; + if(placeholders_count>0) + services._throw("bind variables not supported (yet)"); + + // transcode from $request:charset to connect-string?client_charset + if(cstrClientCharset) { + size_t transcoded_statement_size; + services.transcode(astatement, strlen(astatement), + astatement, transcoded_statement_size, + services.request_charset(), + cstrClientCharset); + } + const char *statement=preprocess_statement(connection, astatement, offset, limit); @@ -255,10 +295,19 @@ public: for(int i=0; i