|
|
| version 1.32, 2003/07/24 10:09:40 | version 1.40, 2003/10/30 12:38:18 |
|---|---|
| Line 38 inline int max(int a, int b) { return a> | Line 38 inline int max(int a, int b) { return a> |
| inline int min(int a, int b){ return a<b?a:b; } | inline int min(int a, int b){ return a<b?a:b; } |
| #endif | #endif |
| /// @test setenv version memory. maybe key/value needs ::malloc_atomic? | /// @todo small memory leaks here |
| static int pa_setenv(const char *name, const char *value, bool do_append) { | static int pa_setenv(const char *name, const char *value, bool do_append) { |
| const char *prev_value=0; | const char *prev_value=0; |
| if(do_append) | if(do_append) |
| Line 70 static int pa_setenv(const char *name, c | Line 70 static int pa_setenv(const char *name, c |
| if(value) { | if(value) { |
| if(prev_value) { | if(prev_value) { |
| // MEM_LEAK_HERE | // MEM_LEAK_HERE |
| char *buf=(char *)::malloc_atomic(strlen(prev_value) | char *buf=(char *)::malloc(strlen(prev_value) |
| +strlen(value) | +strlen(value) |
| +1); | +1); |
| strcpy(buf, prev_value); | strcpy(buf, prev_value); |
| Line 104 static char *lsplit(char **string_ref, c | Line 104 static char *lsplit(char **string_ref, c |
| return result; | return result; |
| } | } |
| static const char *options2env(char *options) { | static const char *options2env(char *options, bool* LowerCaseColumnNames) { |
| while(options) { | while(options) { |
| if(char *key=lsplit(&options, '&')) { | if(char *key=lsplit(&options, '&')) { |
| if(*key) { | if(*key) { |
| if(char *value=lsplit(key, '=')) { | if(char *value=lsplit(key, '=')) { |
| if( strcmp( key, "LowerCaseColumnNames" ) == 0 ) { | |
| if( LowerCaseColumnNames ) | |
| *LowerCaseColumnNames = atoi(value)!=0; | |
| continue; | |
| } | |
| bool do_append=key[strlen(key)-1]=='+'; // PATH+= | bool do_append=key[strlen(key)-1]=='+'; // PATH+= |
| if(do_append) | if(do_append) |
| key[strlen(key)-1]=0; // remove trailing + | key[strlen(key)-1]=0; // remove trailing + |
| Line 138 struct OracleSQL_connection_struct { | Line 144 struct OracleSQL_connection_struct { |
| OCIError *errhp; | OCIError *errhp; |
| OCISvcCtx *svchp; | OCISvcCtx *svchp; |
| OCISession *usrhp; | OCISession *usrhp; |
| bool bLowerCaseColumnNames; | |
| }; | }; |
| struct OracleSQL_query_lobs { | struct OracleSQL_query_lobs { |
| Line 206 public: | Line 214 public: |
| const char *error=dlopen_file_spec? | const char *error=dlopen_file_spec? |
| dlink(dlopen_file_spec):"client library column is empty"; | dlink(dlopen_file_spec):"client library column is empty"; |
| if(!error) { | if(!error) { |
| error=options2env(options); | error=options2env(options, 0); |
| if(!error) | if(!error) |
| OCIInitialize((ub4)OCI_THREADED/*| OCI_OBJECT*/, (dvoid *)0, | OCIInitialize((ub4)OCI_THREADED/*| OCI_OBJECT*/, (dvoid *)0, |
| Line 237 public: | Line 245 public: |
| // connections are cross-request, do not use services._alloc [linked with request] | // connections are cross-request, do not use services._alloc [linked with request] |
| OracleSQL_connection_struct &cs= | OracleSQL_connection_struct &cs= |
| *(OracleSQL_connection_struct *)::calloc(sizeof(OracleSQL_connection_struct), 1); | *(OracleSQL_connection_struct *)::calloc(sizeof(OracleSQL_connection_struct), 1); |
| cs.bLowerCaseColumnNames = true; | |
| char *user=used_only_in_connect_url; | char *user=used_only_in_connect_url; |
| char *service=lsplit(user, '@'); | char *service=lsplit(user, '@'); |
| Line 246 public: | Line 255 public: |
| if(!(user && pwd && service)) | if(!(user && pwd && service)) |
| services._throw("mailformed connect part, must be 'user:pass@service'"); | services._throw("mailformed connect part, must be 'user:pass@service'"); |
| if(const char *error=options2env(options)) | if(const char *error=options2env(options, &cs.bLowerCaseColumnNames)) |
| services._throw(error); | services._throw(error); |
| if(setjmp(cs.mark)) | if(setjmp(cs.mark)) |
| Line 368 public: | Line 377 public: |
| while(length--) { | while(length--) { |
| switch(*from) { | switch(*from) { |
| case '\'': // "'" -> "''" | case '\'': // "'" -> "''" |
| *to++='\''; result++; | *to++='\''; |
| break; | break; |
| } | } |
| *to++=*from++; | *to++=*from++; |
| Line 467 private: // private funcs | Line 476 private: // private funcs |
| o[0]=='/' && | o[0]=='/' && |
| o[1]=='*' && | o[1]=='*' && |
| o[2]=='*') { // name start | o[2]=='*') { // name start |
| const char* saved_o=o; | |
| o+=3; | o+=3; |
| const char *name_begin=o; | const char *name_begin=o; |
| while(*o) | while(*o) |
| Line 475 private: // private funcs | Line 485 private: // private funcs |
| o[1]=='*' && | o[1]=='*' && |
| o[2]=='/' && | o[2]=='/' && |
| o[3]=='\'') { // name end | o[3]=='\'') { // name end |
| saved_o=0; // found, marking that | |
| const char *name_end=o; | const char *name_end=o; |
| o+=4; | o+=4; |
| OracleSQL_query_lobs::Item &item=lobs.items[lobs.count++]; | OracleSQL_query_lobs::Item &item=lobs.items[lobs.count++]; |
| Line 506 private: // private funcs | Line 517 private: // private funcs |
| break; | break; |
| } else | } else |
| o++; // /**skip**/'xxx' | o++; // /**skip**/'xxx' |
| if(saved_o) { | |
| o=saved_o; | |
| *n++=*o++; | |
| } | |
| } else | } else |
| *n++=*o++; | *n++=*o++; |
| } | } |
| Line 618 private: // private funcs | Line 633 private: // private funcs |
| ub2 dtype; | ub2 dtype; |
| text *col_name; | text *col_name; |
| struct { | struct Col { |
| ub2 type; | ub2 type; |
| char *str; | char *str; |
| OCILobLocator *var; | OCILobLocator *var; |
| Line 655 private: // private funcs | Line 670 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 *)cs.errhp)); | (OCIError *)cs.errhp)); |
| Col& col=cols[column_count-1]; | |
| { | { |
| size_t size=(size_t)col_name_len; | size_t length=(size_t)col_name_len; |
| char *ptr=(char *)services.malloc_atomic(size); | char *ptr=(char *)services.malloc_atomic(length+1); |
| tolower(ptr, (char *)col_name, size); | if( cs.bLowerCaseColumnNames ) |
| check(cs, handlers.add_column(cs.sql_error, ptr, size)); | tolower(ptr, (char *)col_name, length); |
| else | |
| memcpy(ptr, col_name, length); | |
| ptr[length]=0; | |
| check(cs, handlers.add_column(cs.sql_error, ptr, length)); | |
| } | } |
| ub2 coerce_type=dtype; | ub2 coerce_type=dtype; |
| Line 670 private: // private funcs | Line 690 private: // private funcs |
| case SQLT_CLOB: | case SQLT_CLOB: |
| { | { |
| check(cs, "alloc output var desc", OCIDescriptorAlloc( | check(cs, "alloc output var desc", OCIDescriptorAlloc( |
| (dvoid *)cs.envhp, (dvoid **)(ptr=&cols[column_count-1].var), | (dvoid *)cs.envhp, (dvoid **)(ptr=&col.var), |
| (ub4)OCI_DTYPE_LOB, | (ub4)OCI_DTYPE_LOB, |
| 0, (dvoid **)0)); | 0, (dvoid **)0)); |
| Line 679 private: // private funcs | Line 699 private: // private funcs |
| } | } |
| default: | default: |
| coerce_type=SQLT_STR; | coerce_type=SQLT_STR; |
| ptr=cols[column_count-1].str=(char *)services.malloc_atomic(MAX_OUT_STRING_LENGTH+1); | ptr=col.str=(char *)services.malloc_atomic(MAX_OUT_STRING_LENGTH+1); |
| size=MAX_OUT_STRING_LENGTH; | size=MAX_OUT_STRING_LENGTH; |
| break; | break; |
| } | } |
| cols[column_count-1].type=coerce_type; | col.type=coerce_type; |
| check(cs, "DefineByPos", OCIDefineByPos( | col.def=0; check(cs, "DefineByPos", OCIDefineByPos( |
| stmthp, &cols[column_count-1].def, cs.errhp, | stmthp, &col.def, cs.errhp, |
| column_count, (ub1 *) ptr, size, | column_count, (ub1 *) ptr, size, |
| coerce_type, (dvoid *) &cols[column_count-1].indicator, | coerce_type, (dvoid *) &col.indicator, |
| (ub2 *)0, (ub2 *)0, OCI_DEFAULT)); | (ub2 *)0, (ub2 *)0, OCI_DEFAULT)); |
| } | } |
| Line 705 private: // private funcs | Line 725 private: // private funcs |
| if(row>=offset) { | if(row>=offset) { |
| check(cs, handlers.add_row(cs.sql_error)); | check(cs, handlers.add_row(cs.sql_error)); |
| for(int i=0; i<column_count; i++) { | for(int i=0; i<column_count; i++) { |
| size_t size=0; | size_t length=0; |
| char* str=0; | char* str=0; |
| if(!cols[i].indicator) // not NULL | if(!cols[i].indicator) // not NULL |
| switch(cols[i].type) { | switch(cols[i].type) { |
| Line 717 private: // private funcs | Line 737 private: // private funcs |
| OCILobLocator *var=(OCILobLocator *)cols[i].var; | OCILobLocator *var=(OCILobLocator *)cols[i].var; |
| OCILobGetLength(cs.svchp, cs.errhp, var, &loblen); | OCILobGetLength(cs.svchp, cs.errhp, var, &loblen); |
| if(loblen) { | if(loblen) { |
| size=(size_t)loblen; | length=(size_t)loblen; |
| str=(char*)services.malloc_atomic(size+1); | str=(char*)services.malloc_atomic(length+1); |
| check(cs, "lobread", OCILobRead(cs.svchp, cs.errhp, | check(cs, "lobread", OCILobRead(cs.svchp, cs.errhp, |
| var, &amtp, offset, (dvoid *) str, | var, &amtp, offset, (dvoid *) str, |
| loblen, (dvoid *)0, | loblen, (dvoid *)0, |
| 0, | 0, |
| (ub2)0, (ub1) SQLCS_IMPLICIT)); | (ub2)0, (ub1) SQLCS_IMPLICIT)); |
| str[size]=0; | str[length]=0; |
| } | } |
| break; | break; |
| } | } |
| default: | default: |
| if(const char *value=cols[i].str) { | if(const char *value=cols[i].str) { |
| size=strlen(str); | length=strlen(value); |
| str=(char*)services.malloc_atomic(size+1); | str=(char*)services.malloc_atomic(length+1); |
| memcpy(str, value, size+1); | memcpy(str, value, length+1); |
| } else { | } else { |
| size=0; | length=0; |
| str=0; | str=0; |
| } | } |
| break; | break; |
| } | } |
| check(cs, handlers.add_row_cell(cs.sql_error, str, size)); | check(cs, handlers.add_row_cell(cs.sql_error, str, length)); |
| } | } |
| } | } |
| } | } |
| Line 1018 void tolower(char *out, const char *in, | Line 1038 void tolower(char *out, const char *in, |
| } | } |
| extern "C" SQL_Driver *SQL_DRIVER_CREATE() { | extern "C" SQL_Driver *SQL_DRIVER_CREATE() { |
| //_asm int 3; | |
| return OracleSQL_driver=new OracleSQL_Driver(); | return OracleSQL_driver=new OracleSQL_Driver(); |
| } | } |