|
|
| version 1.52, 2004/03/04 09:10:13 | version 1.59, 2004/06/18 11:29:55 |
|---|---|
| Line 83 static int pa_setenv(const char *name, c | Line 83 static int pa_setenv(const char *name, c |
| strcat(buf, value); | strcat(buf, value); |
| value=buf; | value=buf; |
| } | } |
| return setenv(name, value, 1/*overwrite*/); | return setenv(name, value, 1/*overwrite*/); |
| } else { | } else { |
| unsetenv(name); | unsetenv(name); |
| Line 139 struct OracleSQL_query_lobs { | Line 138 struct OracleSQL_query_lobs { |
| } *row; | } *row; |
| int count; | int count; |
| }; | }; |
| struct cbf_context_struct { | |
| Connection *connection; | |
| return_rows *rows; | |
| }; | |
| struct Item { | struct Item { |
| const char *name_ptr; size_t name_size; | const char *name_ptr; size_t name_size; |
| char *data_ptr; size_t data_size; | char *data_ptr; size_t data_size; |
| OCILobLocator *locator; | OCILobLocator *locator; |
| OCIBind *bind; | OCIBind *bind; |
| return_rows rows; | return_rows rows; |
| Connection *connection; | |
| } items[MAX_IN_LOBS]; | } items[MAX_IN_LOBS]; |
| int count; | int count; |
| }; | }; |
| Line 173 static sb4 cbf_get_data(dvoid *ctxp, | Line 169 static sb4 cbf_get_data(dvoid *ctxp, |
| ub1 *piecep, | ub1 *piecep, |
| dvoid **indpp, | dvoid **indpp, |
| ub2 **rcodepp); | ub2 **rcodepp); |
| static void tolower(char *out, const char *in, size_t size); | static void tolower_str(char *out, const char *in, size_t size); |
| static void toupper(char *out, const char *in, size_t size); | static void toupper_str(char *out, const char *in, size_t size); |
| static const char *options2env(char *s, Connection::Options* options) { | static const char *options2env(char *s, Connection::Options* options) { |
| while(s) { | while(s) { |
| Line 183 static const char *options2env(char *s, | Line 179 static const char *options2env(char *s, |
| if(char *value=lsplit(key, '=')) { | if(char *value=lsplit(key, '=')) { |
| if( strcmp( key, "ClientCharset" ) == 0 ) { | if( strcmp( key, "ClientCharset" ) == 0 ) { |
| if(options) { | if(options) { |
| toupper(value, value, strlen(value)); | toupper_str(value, value, strlen(value)); |
| options->cstrClientCharset = value; | options->cstrClientCharset = value; |
| } | } |
| continue; | continue; |
| Line 249 public: | Line 245 public: |
| } | } |
| /** connect | /** connect |
| @param used_only_in_connect_url | @param url |
| format: @b user:pass@service? | format: @b user:pass@service? |
| ORACLE_HOME=/u01/app/oracle/product/8.1.5& | ORACLE_HOME=/u01/app/oracle/product/8.1.5& |
| ORA_NLS33=/u01/app/oracle/product/8.1.5/ocommon/nls/admin/data& | ORA_NLS33=/u01/app/oracle/product/8.1.5/ocommon/nls/admin/data& |
| Line 257 public: | Line 253 public: |
| ORA_ENCRYPT_LOGIN=TRUE | ORA_ENCRYPT_LOGIN=TRUE |
| @todo environment manupulation doesnt look thread safe | @todo environment manupulation doesnt look thread safe |
| @todo allocate 'aused_only_in_connect_url' on gc heap, so it can be manipulated directly | |
| */ | */ |
| void connect( | void connect( |
| char *used_only_in_connect_url, | char *url, |
| SQL_Driver_services& services, | SQL_Driver_services& services, |
| void **connection_ref ///< output: Connection * | void **connection_ref ///< output: Connection * |
| ) { | ) |
| { | |
| // connections are cross-request, do not use services._alloc [linked with request] | |
| Connection& connection=*(Connection *)services.malloc(sizeof(Connection)); | Connection& connection=*(Connection *)services.malloc(sizeof(Connection)); |
| connection.services=&services; | connection.services=&services; |
| connection.options.bLowerCaseColumnNames = true; | connection.options.bLowerCaseColumnNames = true; |
| *connection_ref=&connection; | *connection_ref=&connection; |
| char *user=used_only_in_connect_url; | char *user=url; |
| char *service=lsplit(user, '@'); | char *service=lsplit(user, '@'); |
| char *pwd=lsplit(user, ':'); | char *pwd=lsplit(user, ':'); |
| char *options=lsplit(service, '?'); | char *options=lsplit(service, '?'); |
| Line 345 public: | Line 344 public: |
| void disconnect(void *aconnection) { | void disconnect(void *aconnection) { |
| Connection& connection=*static_cast<Connection *>(aconnection); | Connection& connection=*static_cast<Connection *>(aconnection); |
| // free fetch buffers | // free fetch buffers. leave that to GC [no such services func. yet?] |
| /* | |
| for(int i=0; i<MAX_COLS; i++) { | for(int i=0; i<MAX_COLS; i++) { |
| if(void* fetch_buffer=connection.fetch_buffers[i]) | if(void* fetch_buffer=connection.fetch_buffers[i]) |
| ::free(fetch_buffer); | connection.services->free(fetch_buffer); |
| else | else |
| break; | break; |
| } | } |
| */ | |
| // Terminate a user session | // Terminate a user session |
| OCISessionEnd( | OCISessionEnd( |
| Line 372 public: | Line 373 public: |
| OCIHandleFree( | OCIHandleFree( |
| (dvoid *)connection.envhp, (ub4)OCI_HTYPE_ENV); | (dvoid *)connection.envhp, (ub4)OCI_HTYPE_ENV); |
| // connections are cross-request, do not use services._alloc [linked with request] | // free connection. leave that to GC [no such services func. yet?] |
| ::free(&connection); | // connection.services->free(&connection); |
| } | } |
| void commit(void *aconnection) { | void commit(void *aconnection) { |
| Connection& connection=*static_cast<Connection *>(aconnection); | Connection& connection=*static_cast<Connection *>(aconnection); |
| Line 420 public: | Line 421 public: |
| SQL_Driver_query_event_handlers& handlers) | SQL_Driver_query_event_handlers& handlers) |
| { | { |
| Connection& connection=*static_cast<Connection *>(aconnection); | Connection& connection=*static_cast<Connection *>(aconnection); |
| const char* cstrClientCharset=connection.options.cstrClientCharset; | |
| OracleSQL_query_lobs lobs={{0}, 0}; | OracleSQL_query_lobs lobs={{0}, 0}; |
| OCIStmt *stmthp=0; | OCIStmt *stmthp=0; |
| SQL_Driver_services& services=*connection.services; | SQL_Driver_services& services=*connection.services; |
| // transcode from $request:charset to connect-string?client_charset | // transcode from $request:charset to connect-string?client_charset |
| size_t transcoded_statement_size; | if(cstrClientCharset) { |
| if(const char* cstrClientCharset=connection.options.cstrClientCharset) | size_t transcoded_statement_size; |
| services.transcode(astatement, strlen(astatement), | services.transcode(astatement, strlen(astatement), |
| astatement, transcoded_statement_size, | astatement, transcoded_statement_size, |
| services.request_charset(), | services.request_charset(), |
| cstrClientCharset); | cstrClientCharset); |
| } | |
| bool failed=false; | bool failed=false; |
| if(setjmp(connection.mark)) { | if(setjmp(connection.mark)) { |
| Line 448 public: | Line 451 public: |
| (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); | (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); |
| { | { |
| for(int i=0; i<lobs.count; i++) { | for(int i=0; i<lobs.count; i++) { |
| OracleSQL_query_lobs::Item &item=lobs.items[i]; | |
| check(connection, "alloc output var desc", OCIDescriptorAlloc( | check(connection, "alloc output var desc", OCIDescriptorAlloc( |
| (dvoid *)connection.envhp, (dvoid **)&lobs.items[i].locator, (ub4)OCI_DTYPE_LOB, 0, 0)); | (dvoid *)connection.envhp, (dvoid **)&item.locator, (ub4)OCI_DTYPE_LOB, 0, 0)); |
| check(connection, "bind output", OCIBindByPos(stmthp, | char placeholder_buf[MAX_STRING]; |
| &lobs.items[i].bind, connection.errhp, | sb4 placeh_len=snprintf(placeholder_buf, sizeof(placeholder_buf), |
| (ub4)1+i, | ":%.*s", item.name_size, item.name_ptr); |
| (dvoid *)&lobs.items[i].locator, | check(connection, "bind lob", OCIBindByName(stmthp, |
| (sword)sizeof (lobs.items[i].locator), SQLT_CLOB, (dvoid *)0, | &item.bind, connection.errhp, |
| (text*)placeholder_buf, placeh_len, | |
| (dvoid *)&item.locator, | |
| (sword)sizeof (item.locator), SQLT_CLOB, (dvoid *)0, | |
| (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, OCI_DATA_AT_EXEC)); | (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, OCI_DATA_AT_EXEC)); |
| lobs.items[i].rows.count=0; | item.rows.count=0; |
| OracleSQL_query_lobs::cbf_context_struct cbf_context={&connection, &lobs.items[i].rows}; | item.connection=&connection; |
| check(connection, "bind dynamic", OCIBindDynamic( | check(connection, "bind dynamic", OCIBindDynamic( |
| lobs.items[i].bind, connection.errhp, | item.bind, connection.errhp, |
| (dvoid *) &cbf_context, cbf_no_data, | (dvoid *) &item, cbf_no_data, |
| (dvoid *) &cbf_context, cbf_get_data)); | (dvoid *) &item, cbf_get_data)); |
| } | } |
| } | } |
| Line 650 private: // private funcs | Line 657 private: // private funcs |
| OCIStmt *stmthp, unsigned long offset, unsigned long limit, | OCIStmt *stmthp, unsigned long offset, unsigned long limit, |
| SQL_Driver_query_event_handlers& handlers) | SQL_Driver_query_event_handlers& handlers) |
| { | { |
| const char* cstrClientCharset=connection.options.cstrClientCharset; | |
| SQL_Driver_services& services=*connection.services; | SQL_Driver_services& services=*connection.services; |
| ub4 prefetch_rows=100; | ub4 prefetch_rows=100; |
| Line 705 private: // private funcs | Line 713 private: // private funcs |
| (dvoid**) &col_name, (ub4 *) &col_name_len, (ub4)OCI_ATTR_NAME, | (dvoid**) &col_name, (ub4 *) &col_name_len, (ub4)OCI_ATTR_NAME, |
| (OCIError *)connection.errhp)); | (OCIError *)connection.errhp)); |
| // transcode to $request:charset from connect-string?client_charset | // transcode to $request:charset from connect-string?client_charset |
| if(const char* cstrClientCharset=connection.options.cstrClientCharset) { | if(cstrClientCharset) { |
| services.transcode(col_name, col_name_len, | services.transcode(col_name, col_name_len, |
| col_name, col_name_len, | col_name, col_name_len, |
| cstrClientCharset, | cstrClientCharset, |
| Line 717 private: // private funcs | Line 725 private: // private funcs |
| size_t length=(size_t)col_name_len; | size_t length=(size_t)col_name_len; |
| char *ptr=(char *)services.malloc_atomic(length+1); | char *ptr=(char *)services.malloc_atomic(length+1); |
| if( connection.options.bLowerCaseColumnNames ) | if( connection.options.bLowerCaseColumnNames ) |
| tolower(ptr, col_name, length); | tolower_str(ptr, col_name, length); |
| else | else |
| memcpy(ptr, col_name, length); | memcpy(ptr, col_name, length); |
| ptr[length]=0; | ptr[length]=0; |
| Line 744 private: // private funcs | Line 752 private: // private funcs |
| char*& buf=connection.fetch_buffers[column_count-1]; | char*& buf=connection.fetch_buffers[column_count-1]; |
| ptr=buf; // get cached buffer | ptr=buf; // get cached buffer |
| if(!ptr) // allocate if needed, caching it | if(!ptr) // allocate if needed, caching it |
| ptr=buf=(char *)::/*see disconnect*/malloc(MAX_OUT_STRING_LENGTH+1/*terminator*/); | ptr=buf=(char *)services.malloc_atomic(MAX_OUT_STRING_LENGTH+1/*terminator*/); |
| col.str=(char*)ptr; | col.str=(char*)ptr; |
| size=MAX_OUT_STRING_LENGTH; | size=MAX_OUT_STRING_LENGTH; |
| break; | break; |
| Line 824 private: // private funcs | Line 832 private: // private funcs |
| if(str && length) | if(str && length) |
| { | { |
| // transcode to $request:charset from connect-string?client_charset | // transcode to $request:charset from connect-string?client_charset |
| if(const char* cstrClientCharset=connection.options.cstrClientCharset) { | if(cstrClientCharset) |
| const char* dest; | |
| size_t dest_length; | |
| services.transcode(str, length, | services.transcode(str, length, |
| dest, dest_length, | str, length, |
| cstrClientCharset, | cstrClientCharset, |
| services.request_charset()); | services.request_charset()); |
| str=dest; | |
| length=dest_length; | |
| } | |
| } | } |
| check(connection, handlers.add_row_cell(connection.sql_error, str, length)); | check(connection, handlers.add_row_cell(connection.sql_error, str, length)); |
| Line 894 private: // conn client library funcs | Line 897 private: // conn client library funcs |
| ub2 dty, dvoid *indp, ub2 *alenp, ub2 *rcodep, | ub2 dty, dvoid *indp, ub2 *alenp, ub2 *rcodep, |
| ub4 maxarr_len, ub4 *curelep, ub4 mode)); | ub4 maxarr_len, ub4 *curelep, ub4 mode)); |
| OCI_DECL(BindByName, (OCIStmt *stmtp, OCIBind **bindp, OCIError *errhp, | |
| text* placeholder, sb4 placeh_len, dvoid *valuep, sb4 value_sz, | |
| ub2 dty, dvoid *indp, ub2 *alenp, ub2 *rcodep, | |
| ub4 maxarr_len, ub4 *curelep, ub4 mode)); | |
| OCI_DECL(BindDynamic, (OCIBind *bindp, OCIError *errhp, dvoid *ictxp, | OCI_DECL(BindDynamic, (OCIBind *bindp, OCIError *errhp, dvoid *ictxp, |
| OCICallbackInBind icbfp, dvoid *octxp, | OCICallbackInBind icbfp, dvoid *octxp, |
| OCICallbackOutBind ocbfp)); | OCICallbackOutBind ocbfp)); |
| Line 985 private: // conn client library funcs li | Line 993 private: // conn client library funcs li |
| OCI_LINK(Initialize); | OCI_LINK(Initialize); |
| OCI_LINK(EnvInit); | OCI_LINK(EnvInit); |
| OCI_LINK(AttrGet); OCI_LINK(AttrSet); | OCI_LINK(AttrGet); OCI_LINK(AttrSet); |
| OCI_LINK(BindByPos); OCI_LINK(BindDynamic); | OCI_LINK(BindByPos); OCI_LINK(BindByName); OCI_LINK(BindDynamic); |
| OCI_LINK(DefineByPos); | OCI_LINK(DefineByPos); |
| OCI_LINK(DescriptorAlloc); OCI_LINK(DescriptorFree); | OCI_LINK(DescriptorAlloc); OCI_LINK(DescriptorFree); |
| OCI_LINK(ErrorGet); | OCI_LINK(ErrorGet); |
| Line 1090 static sb4 cbf_get_data(dvoid *ctxp, | Line 1098 static sb4 cbf_get_data(dvoid *ctxp, |
| ub1 *piecep, | ub1 *piecep, |
| dvoid **indpp, | dvoid **indpp, |
| ub2 **rcodepp) { | ub2 **rcodepp) { |
| OracleSQL_query_lobs::cbf_context_struct &context= | OracleSQL_query_lobs::Item& context=*static_cast<OracleSQL_query_lobs::Item*>(ctxp); |
| *(OracleSQL_query_lobs::cbf_context_struct *)ctxp; | |
| if(index==0) { | if(index==0) { |
| static ub4 rows; | static ub4 rows; |
| Line 1099 static sb4 cbf_get_data(dvoid *ctxp, | Line 1106 static sb4 cbf_get_data(dvoid *ctxp, |
| OracleSQL_driver->OCIAttrGet( | OracleSQL_driver->OCIAttrGet( |
| (CONST dvoid *) bindp, OCI_HTYPE_BIND, (dvoid *)&rows, | (CONST dvoid *) bindp, OCI_HTYPE_BIND, (dvoid *)&rows, |
| (ub4 *)sizeof(ub2), OCI_ATTR_ROWS_RETURNED, context.connection->errhp)) ; | (ub4 *)sizeof(ub2), OCI_ATTR_ROWS_RETURNED, context.connection->errhp)) ; |
| context.rows->count=(ub2)rows; | context.rows.count=(ub2)rows; |
| context.rows->row=(OracleSQL_query_lobs::return_rows::return_row *) | context.rows.row=(OracleSQL_query_lobs::return_rows::return_row *) |
| context.connection->services->malloc_atomic(sizeof(OracleSQL_query_lobs::return_rows::return_row)*rows); | context.connection->services->malloc_atomic(sizeof(OracleSQL_query_lobs::return_rows::return_row)*rows); |
| } | } |
| OracleSQL_query_lobs::return_rows::return_row &var=context.rows->row[index]; | OracleSQL_query_lobs::return_rows::return_row &var=context.rows.row[index]; |
| check(*context.connection, "alloc output var desc dynamic", OracleSQL_driver->OCIDescriptorAlloc( | check(*context.connection, "alloc output var desc dynamic", OracleSQL_driver->OCIDescriptorAlloc( |
| (dvoid *) context.connection->envhp, (dvoid **)&var.locator, | (dvoid *) context.connection->envhp, (dvoid **)&var.locator, |
| Line 1120 static sb4 cbf_get_data(dvoid *ctxp, | Line 1127 static sb4 cbf_get_data(dvoid *ctxp, |
| return OCI_CONTINUE; | return OCI_CONTINUE; |
| } | } |
| static void tolower(char *out, const char *in, size_t size) { | static void tolower_str(char *out, const char *in, size_t size) { |
| while(size--) | while(size--) |
| *out++=(char)tolower(*in++); | *out++=(char)tolower(*in++); |
| } | } |
| static void toupper(char *out, const char *in, size_t size) { | static void toupper_str(char *out, const char *in, size_t size) { |
| while(size--) | while(size--) |
| *out++=(char)toupper(*in++); | *out++=(char)toupper(*in++); |
| } | } |