|
|
| version 1.47, 2021/11/03 14:51:51 | version 1.48, 2021/11/03 15:14:05 |
|---|---|
| Line 78 static char* rsplit(char* string, char d | Line 78 static char* rsplit(char* string, char d |
| return v+1; | return v+1; |
| } | } |
| } | } |
| return NULL; | return NULL; |
| } | } |
| static void toupper_str(char *out, const char *in, size_t size){ | static void toupper_str(char *out, const char *in, size_t size){ |
| Line 116 public: | Line 116 public: |
| /// initialize driver by loading sql dynamic link library | /// initialize driver by loading sql dynamic link library |
| const char *initialize(char *dlopen_file_spec){ | const char *initialize(char *dlopen_file_spec){ |
| return dlopen_file_spec? | return dlopen_file_spec ? dlink(dlopen_file_spec) : "client library column is empty"; |
| dlink(dlopen_file_spec):"client library column is empty"; | |
| } | } |
| #define throwPQerror connection.services->_throw(PQerrorMessage(connection.conn)) | #define throwPQerror connection.services->_throw(PQerrorMessage(connection.conn)) |
| #define PQclear_throw(msg) { \ | #define PQclear_throw(msg) { \ |
| PQclear(res); \ | PQclear(res); \ |
| connection.services->_throw(msg); \ | connection.services->_throw(msg); \ |
| } | } |
| #define PQclear_throwPQerror PQclear_throw(PQerrorMessage(connection.conn)) | #define PQclear_throwPQerror PQclear_throw(PQerrorMessage(connection.conn)) |
| /** connect | /** connect |
| Line 136 public: | Line 135 public: |
| autocommit=0& // 1 -- each statement is commited automatically, only when with_default_transaction enabled | autocommit=0& // 1 -- each statement is commited automatically, only when with_default_transaction enabled |
| standard_conforming_strings=1& // 0 -- escape \ char that could be needed for old servers | standard_conforming_strings=1& // 0 -- escape \ char that could be needed for old servers |
| */ | */ |
| void connect( | void connect(char* url, SQL_Driver_services& services, void** connection_ref /* < output: Connection* */){ |
| char* url, | |
| SQL_Driver_services& services, | |
| void** connection_ref ///< output: Connection* | |
| ){ | |
| char* user=url; | char* user=url; |
| char* host=rsplit(user, '@'); | char* host=rsplit(user, '@'); |
| char* db=lsplit(host, '/'); | char* db=lsplit(host, '/'); |
| Line 160 public: | Line 155 public: |
| connection.autocommit=true; | connection.autocommit=true; |
| connection.standard_conforming_strings=true; | connection.standard_conforming_strings=true; |
| connection.conn=PQsetdbLogin( | connection.conn=PQsetdbLogin( (host && strcasecmp(host, "local") == 0) ? NULL /* local Unix domain socket */ : host, port, NULL, NULL, db, user, pwd); |
| (host&&strcasecmp(host, "local")==0)?NULL/* local Unix domain socket */:host, port, | |
| NULL, NULL, db, user, pwd); | |
| if(!connection.conn) | if(!connection.conn) |
| services._throw("PQsetdbLogin failed"); | services._throw("PQsetdbLogin failed"); |
| Line 238 public: | Line 231 public: |
| // charset here is services.request_charset(), not connection.client_charset | // charset here is services.request_charset(), not connection.client_charset |
| // thus we can't use the sql server quoting support | // thus we can't use the sql server quoting support |
| const char* quote(void *aconnection, const char *str, unsigned int length) | const char* quote(void *aconnection, const char *str, unsigned int length){ |
| { | |
| Connection& connection=*static_cast<Connection*>(aconnection); | Connection& connection=*static_cast<Connection*>(aconnection); |
| const char* from; | const char* from; |
| Line 292 public: | Line 284 public: |
| return result; | return result; |
| } | } |
| void query(void *aconnection, | void query(void *aconnection, const char *astatement, size_t placeholders_count, Placeholder* placeholders, unsigned long offset, unsigned long limit, SQL_Driver_query_event_handlers& handlers ){ |
| const char *astatement, | |
| size_t placeholders_count, Placeholder* placeholders, | |
| unsigned long offset, unsigned long limit, | |
| SQL_Driver_query_event_handlers& handlers | |
| ){ | |
| Connection& connection=*static_cast<Connection*>(aconnection); | Connection& connection=*static_cast<Connection*>(aconnection); |
| SQL_Driver_services& services=*connection.services; | SQL_Driver_services& services=*connection.services; |
| PGconn *conn=connection.conn; | PGconn *conn=connection.conn; |
| Line 317 public: | Line 304 public: |
| if(transcode_needed){ | if(transcode_needed){ |
| // transcode query from $request:charset to ?ClientCharset | // transcode query from $request:charset to ?ClientCharset |
| statement_size=strlen(astatement); | statement_size=strlen(astatement); |
| services.transcode(astatement, statement_size, | services.transcode(astatement, statement_size, astatement, statement_size, request_charset, client_charset); |
| astatement, statement_size, | |
| request_charset, | |
| client_charset); | |
| } | } |
| const char *statement=_preprocess_statement(connection, astatement, statement_size, offset, limit); | const char *statement=_preprocess_statement(connection, astatement, statement_size, offset, limit); |
| Line 339 public: | Line 323 public: |
| SQL_Error sql_error; | 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|... |
| Line 376 public: | Line 360 public: |
| 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, client_charset, request_charset); |
| str, length, | |
| client_charset, | |
| request_charset); | |
| CHECK(handlers.add_column(sql_error, str, length)); | CHECK(handlers.add_column(sql_error, str, length)); |
| } | } |
| Line 473 cleanup: | Line 454 cleanup: |
| } | } |
| private: | private: |
| void _bind_parameters( | void _bind_parameters( size_t placeholders_count, Placeholder* placeholders, const char** paramValues, Connection& connection, bool transcode_needed){ |
| size_t placeholders_count, | |
| Placeholder* placeholders, | |
| const char** paramValues, | |
| Connection& connection, | |
| bool transcode_needed | |
| ){ | |
| for(size_t i=0; i<placeholders_count; i++){ | for(size_t i=0; i<placeholders_count; i++){ |
| Placeholder& ph=placeholders[i]; | Placeholder& ph=placeholders[i]; |
| if(transcode_needed){ | if(transcode_needed){ |
| size_t name_length; | size_t name_length; |
| connection.services->transcode(ph.name, strlen(ph.name), | connection.services->transcode(ph.name, strlen(ph.name), ph.name, name_length, connection.services->request_charset(), connection.client_charset); |
| ph.name, name_length, | |
| connection.services->request_charset(), | |
| connection.client_charset); | |
| if(ph.value) { | if(ph.value) { |
| size_t value_length; | size_t value_length; |
| connection.services->transcode(ph.value, strlen(ph.value), | connection.services->transcode(ph.value, strlen(ph.value), ph.value, value_length, connection.services->request_charset(), connection.client_charset); |
| ph.value, value_length, | |
| connection.services->request_charset(), | |
| connection.client_charset); | |
| } | } |
| } | } |
| int name_number=atoi(ph.name); | int name_number=atoi(ph.name); |
| Line 513 private: | Line 482 private: |
| throwPQerror; | throwPQerror; |
| } | } |
| const char *_preprocess_statement( | const char *_preprocess_statement(Connection& connection, const char *astatement, size_t statement_size, unsigned long offset, unsigned long limit){ |
| Connection& connection, | |
| const char *astatement, | |
| size_t statement_size, | |
| unsigned long offset, | |
| unsigned long limit | |
| ){ | |
| PGconn *conn=connection.conn; | PGconn *conn=connection.conn; |
| if(!statement_size) | if(!statement_size) |
| Line 552 private: | Line 515 private: |
| const char* saved_o=o; | const char* saved_o=o; |
| o+=3; | o+=3; |
| while(*o) | while(*o) |
| if( | if(o[0]=='*' && o[1]=='*' && o[2]=='/' && o[3]=='\'') { // name end |
| o[0]=='*' && | |
| o[1]=='*' && | |
| o[2]=='/' && | |
| o[3]=='\'') { // name end | |
| saved_o=0; // found, marking that | saved_o=0; // found, marking that |
| o+=4; | o+=4; |
| Oid oid=lo_creat(conn, INV_READ|INV_WRITE); | Oid oid=lo_creat(conn, INV_READ|INV_WRITE); |
| Line 714 private: // conn client library funcs li | Line 673 private: // conn client library funcs li |
| DLINK(PQexecParams); | DLINK(PQexecParams); |
| DLINK(PQftype); | DLINK(PQftype); |
| DLINK(PQescapeStringConn); | DLINK(PQescapeStringConn); |
| DLINK(lo_open); DLINK(lo_close); | DLINK(lo_open); DLINK(lo_close); |
| DLINK(lo_read); DLINK(lo_write); | DLINK(lo_read); DLINK(lo_write); |
| DLINK(lo_lseek); DLINK(lo_creat); | DLINK(lo_lseek); DLINK(lo_creat); |
| DLINK(lo_tell); DLINK(lo_unlink); | DLINK(lo_tell); DLINK(lo_unlink); |
| DLINK(lo_import); DLINK(lo_export); | DLINK(lo_import); DLINK(lo_export); |
| return 0; | return 0; |
| } | } |