|
|
| version 1.31, 2008/07/01 13:40:33 | version 1.34, 2008/12/25 02:33:56 |
|---|---|
| Line 126 public: | Line 126 public: |
| charset=value& // transcode by server with 'SET CLIENT_ENCODING=value' | charset=value& // transcode by server with 'SET CLIENT_ENCODING=value' |
| datestyle=value& // 'SET DATESTYLE=value' available values are: ISO|SQL|Postgres|European|US|German [default=ISO] | datestyle=value& // 'SET DATESTYLE=value' available values are: ISO|SQL|Postgres|European|US|German [default=ISO] |
| autocommit=1& // each transaction is commited automatically (default) | autocommit=1& // each transaction is commited automatically (default) |
| WithoutDefaultTransaction=0 // 1 -- disable auto commit, 'BEGIN TRAN' at connection start and COMMIT/ROLLBACK at the end [can't be used together with autocommit option] | WithoutDefaultTransaction=0 // 1 -- disable any BEGIN TRAN/COMMIT/ROLLBACK [can NOT be used with autocommit option] |
| */ | */ |
| void connect( | void connect( |
| char* url, | char* url, |
| Line 206 public: | Line 206 public: |
| _execute_cmd(connection, statement); | _execute_cmd(connection, statement); |
| } | } |
| _begin_transaction(connection); | _transaction_begin(connection); |
| } | } |
| void disconnect(void *aconnection){ | void disconnect(void *aconnection){ |
| Line 217 public: | Line 217 public: |
| void commit(void *aconnection){ | void commit(void *aconnection){ |
| Connection& connection=*static_cast<Connection*>(aconnection); | Connection& connection=*static_cast<Connection*>(aconnection); |
| if(!connection.without_default_transactions){ | _transaction_commit(connection); |
| _execute_cmd(connection, "COMMIT"); | _transaction_begin(connection); |
| } | |
| _begin_transaction(connection); | |
| } | } |
| void rollback(void *aconnection){ | void rollback(void *aconnection){ |
| Connection& connection=*static_cast<Connection*>(aconnection); | Connection& connection=*static_cast<Connection*>(aconnection); |
| if(!connection.without_default_transactions){ | _transaction_rollback(connection); |
| _execute_cmd(connection, "ROLLBACK"); | _transaction_begin(connection); |
| } | |
| _begin_transaction(connection); | |
| } | } |
| bool ping(void *aconnection) { | bool ping(void *aconnection) { |
| Line 287 public: | Line 283 public: |
| if(!res) | if(!res) |
| throwPQerror; | throwPQerror; |
| bool failed=false; | |
| SQL_Error sql_error; | |
| switch(PQresultStatus(res)) { | switch(PQresultStatus(res)) { |
| case PGRES_EMPTY_QUERY: | case PGRES_EMPTY_QUERY: |
| PQclear_throw("no query"); | PQclear_throw("no query"); |
| break; | break; |
| case PGRES_COMMAND_OK: // empty result: insert|delete|update|... | case PGRES_COMMAND_OK: // empty result: insert|delete|update|... |
| PQclear(res); | PQclear(res); |
| if(connection.autocommit) | |
| commit(aconnection); | |
| return; | return; |
| case PGRES_TUPLES_OK: | case PGRES_TUPLES_OK: |
| break; | break; |
| Line 301 public: | Line 302 public: |
| break; | break; |
| } | } |
| int column_count=PQnfields(res); | |
| if(!column_count) | |
| PQclear_throw("result contains no columns"); | |
| bool failed=false; | |
| SQL_Error sql_error; | |
| #define CHECK(afailed) \ | #define CHECK(afailed) \ |
| if(afailed) { \ | if(afailed) { \ |
| failed=true; \ | failed=true; \ |
| goto cleanup; \ | goto cleanup; \ |
| } | } |
| int column_count=PQnfields(res); | |
| if(!column_count) | |
| PQclear_throw("result contains no columns"); | |
| if(column_count>MAX_COLS) | if(column_count>MAX_COLS) |
| column_count=MAX_COLS; | column_count=MAX_COLS; |
| Line 320 public: | Line 319 public: |
| bool transcode_column[MAX_COLS]; | bool transcode_column[MAX_COLS]; |
| for(int i=0; i<column_count; i++){ | for(int i=0; i<column_count; i++){ |
| char *name=PQfname(res, i); | |
| size_t length=strlen(name); | |
| column_types[i]=PQftype(res, i); | column_types[i]=PQftype(res, i); |
| switch(column_types[i]){ | switch(column_types[i]){ |
| case BOOLOID: | case BOOLOID: |
| Line 342 public: | Line 339 public: |
| transcode_column[i]=transcode_needed; | transcode_column[i]=transcode_needed; |
| break; | break; |
| } | } |
| char *name=PQfname(res, i); | |
| size_t length=strlen(name); | |
| char* strm=(char*)services.malloc(length+1); | char* strm=(char*)services.malloc(length+1); |
| memcpy(strm, name, length+1); | memcpy(strm, name, length+1); |
| const char* str=strm; | const char* str=strm; |
| if(transcode_needed) | if(transcode_needed) // transcode column name from ?ClientCharset to $request:charset |
| // transcode column name from ?ClientCharset to $request:charset | |
| services.transcode(str, length, | services.transcode(str, length, |
| str, length, | str, length, |
| client_charset, | client_charset, |
| Line 410 public: | Line 408 public: |
| } | } |
| if(str && length && transcode_column[i]){ | if(str && length && transcode_column[i]){ |
| //services._throw("tr"); | |
| // transcode cell value from ?ClientCharset to $request:charset | // transcode cell value from ?ClientCharset to $request:charset |
| services.transcode(str, length, | services.transcode(str, length, |
| str, length, | str, length, |
| Line 426 cleanup: | Line 423 cleanup: |
| if(failed) | if(failed) |
| services._throw(sql_error); | services._throw(sql_error); |
| commit(aconnection); | if(connection.autocommit) |
| commit(aconnection); | |
| } | } |
| private: | private: |
| Line 441 private: | Line 439 private: |
| Placeholder& ph=placeholders[i]; | Placeholder& ph=placeholders[i]; |
| if(transcode_needed){ | if(transcode_needed){ |
| size_t name_length; | size_t name_length; |
| size_t value_length; | |
| connection.services->transcode(ph.name, strlen(ph.name), | connection.services->transcode(ph.name, strlen(ph.name), |
| ph.name, name_length, | ph.name, name_length, |
| connection.services->request_charset(), | connection.services->request_charset(), |
| connection.client_charset); | connection.client_charset); |
| if(ph.value) { | if(ph.value) { |
| size_t value_length; | |
| connection.services->transcode(ph.value, strlen(ph.value), | connection.services->transcode(ph.value, strlen(ph.value), |
| ph.value, value_length, | ph.value, value_length, |
| connection.services->request_charset(), | connection.services->request_charset(), |
| Line 455 private: | Line 453 private: |
| } | } |
| } | } |
| int name_numner=atoi(ph.name); | int name_numner=atoi(ph.name); |
| if(name_numner <= 0 || name_numner > placeholders_count) | if(name_numner <= 0 || (size_t)name_numner > placeholders_count) |
| connection.services->_throw("bad bind parameter key"); | connection.services->_throw("bad bind parameter key"); |
| paramValues[name_numner-1]=ph.value; | paramValues[name_numner-1]=ph.value; |
| Line 463 private: | Line 461 private: |
| } | } |
| /** | void _transaction_begin(Connection& connection){ |
| Executes a query and throw away the result. | _execute_transactions_cmd(connection, "BEGIN"); |
| */ | } |
| void _transaction_commit(Connection& connection){ | |
| _execute_transactions_cmd(connection, "COMMIT"); | |
| } | |
| void _transaction_rollback(Connection& connection){ | |
| _execute_transactions_cmd(connection, "ROLLBACK"); | |
| } | |
| void _execute_transactions_cmd(const Connection& connection, const char *query){ | |
| if(!connection.without_default_transactions) // with option ?WithoutDefaultTransaction=1 user must execute BEGIN/COMMIT/ROLLBACK by himself | |
| _execute_cmd(connection, query); | |
| } | |
| // executes a query and throw away the result. | |
| void _execute_cmd(const Connection& connection, const char *query){ | void _execute_cmd(const Connection& connection, const char *query){ |
| if(PGresult *res=PQexec(connection.conn, query)) | if(PGresult *res=PQexec(connection.conn, query)) |
| PQclear(res); // throw out the result [don't need but must call] | PQclear(res); // throw away the result [don't need but must call] |
| else | else |
| throwPQerror; | throwPQerror; |
| } | } |
| void _begin_transaction(Connection& connection){ | |
| if(!connection.without_default_transactions) | |
| _execute_cmd(connection, "BEGIN"); | |
| } | |
| const char *_preprocess_statement( | const char *_preprocess_statement( |
| Connection& connection, | Connection& connection, |
| const char *astatement, | const char *astatement, |