--- sql/oracle/parser3oracle.C 2004/01/30 07:29:10 1.50 +++ sql/oracle/parser3oracle.C 2004/08/03 11:15:27 1.63 @@ -7,7 +7,20 @@ 2001.07.30 using Oracle 8.1.6 [@test tested with Oracle 7.x.x] */ -static const char *RCSId="$Id: parser3oracle.C,v 1.50 2004/01/30 07:29:10 paf Exp $"; +/* +prob: + kgepop: no error frame to pop to for error 21500 + + +> I happy to tell you that I have solved the problem. + +Excellent news. + +> By allocating a separate +> environment handle for every database handle I share +*/ + +static const char *RCSId="$Id: parser3oracle.C,v 1.63 2004/08/03 11:15:27 paf Exp $"; #include "config_includes.h" @@ -19,6 +32,7 @@ static const char *RCSId="$Id: parser3or #define MAX_IN_LOBS 5 #define MAX_LOB_NAME_LENGTH 100 #define MAX_OUT_STRING_LENGTH 4000 +#define MAX_BINDS 100 #define EMPTY_CLOB_FUNC_CALL "empty_clob()" @@ -44,6 +58,8 @@ inline int min(int a, int b){ return a(aconnection); - // free fetch buffers + // free fetch buffers. leave that to GC [no such services func. yet?] + /* for(int i=0; ifree(fetch_buffer); else break; - } + } + */ // Terminate a user session OCISessionEnd( @@ -372,8 +392,8 @@ public: OCIHandleFree( (dvoid *)connection.envhp, (ub4)OCI_HTYPE_ENV); - // connections are cross-request, do not use services._alloc [linked with request] - ::free(&connection); + // free connection. leave that to GC [no such services func. yet?] + // connection.services->free(&connection); } void commit(void *aconnection) { Connection& connection=*static_cast(aconnection); @@ -415,29 +435,37 @@ public: *to=0; return result; } - void query(void *aconnection, - const char *astatement, unsigned long offset, unsigned long limit, + 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) { + Connection& connection=*static_cast(aconnection); - OracleSQL_query_lobs lobs={{0}, 0}; + const char* cstrClientCharset=connection.options.cstrClientCharset; + Query_lobs lobs={{0}, 0}; OCIStmt *stmthp=0; SQL_Driver_services& services=*connection.services; // transcode from $request:charset to connect-string?client_charset - size_t transcoded_statement_size; - if(const char* cstrClientCharset=connection.options.cstrClientCharset) + if(cstrClientCharset) { + size_t transcoded_xxx_size; services.transcode(astatement, strlen(astatement), - astatement, transcoded_statement_size, + astatement, transcoded_xxx_size, services.request_charset(), cstrClientCharset); + } bool failed=false; if(setjmp(connection.mark)) { failed=true; goto cleanup; } else { + if(placeholders_count>MAX_BINDS) + fail(connection, "too many bind variables"); + const char *statement=preprocess_statement(connection, astatement, lobs); check(connection, "HandleAlloc STMT", OCIHandleAlloc( @@ -446,30 +474,121 @@ public: OCIStmtPrepare(stmthp, connection.errhp, (unsigned char *)statement, (ub4)strlen((char *)statement), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT)); + + struct Bind_info { + OCIBind *bind; + sb2 indicator; + }; + + int binds_size=sizeof(Bind_info) * placeholders_count; + Bind_info* binds=static_cast(services.malloc_atomic(binds_size)); { + for(size_t i=0; icount; r++) { OCILobLocator *locator=rows->row[r].locator; check(connection, "lobwrite", OCILobWrite ( @@ -650,6 +769,7 @@ private: // private funcs OCIStmt *stmthp, unsigned long offset, unsigned long limit, SQL_Driver_query_event_handlers& handlers) { + const char* cstrClientCharset=connection.options.cstrClientCharset; SQL_Driver_services& services=*connection.services; ub4 prefetch_rows=100; @@ -666,7 +786,7 @@ private: // private funcs OCIParam *mypard; ub2 dtype; - text *col_name; + const char* col_name; struct Col { ub2 type; @@ -704,13 +824,20 @@ private: // private funcs (dvoid*) mypard, (ub4)OCI_DTYPE_PARAM, (dvoid**) &col_name, (ub4 *) &col_name_len, (ub4)OCI_ATTR_NAME, (OCIError *)connection.errhp)); - + // transcode to $request:charset from connect-string?client_charset + if(cstrClientCharset) { + services.transcode(col_name, col_name_len, + col_name, col_name_len, + cstrClientCharset, + services.request_charset()); + } + Col& col=cols[column_count-1]; { size_t length=(size_t)col_name_len; char *ptr=(char *)services.malloc_atomic(length+1); if( connection.options.bLowerCaseColumnNames ) - tolower(ptr, (char *)col_name, length); + tolower_str(ptr, col_name, length); else memcpy(ptr, col_name, length); ptr[length]=0; @@ -737,7 +864,7 @@ private: // private funcs char*& buf=connection.fetch_buffers[column_count-1]; ptr=buf; // get cached buffer 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; size=MAX_OUT_STRING_LENGTH; break; @@ -771,7 +898,14 @@ private: // private funcs for(int i=0; i(ctxp); if(index==0) { static ub4 rows; @@ -1092,12 +1232,12 @@ static sb4 cbf_get_data(dvoid *ctxp, OracleSQL_driver->OCIAttrGet( (CONST dvoid *) bindp, OCI_HTYPE_BIND, (dvoid *)&rows, (ub4 *)sizeof(ub2), OCI_ATTR_ROWS_RETURNED, context.connection->errhp)) ; - context.rows->count=(ub2)rows; - 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.rows.count=(ub2)rows; + context.rows.row=(Query_lobs::return_rows::return_row *) + context.connection->services->malloc_atomic(sizeof(Query_lobs::return_rows::return_row)*rows); } - OracleSQL_query_lobs::return_rows::return_row &var=context.rows->row[index]; + Query_lobs::return_rows::return_row &var=context.rows.row[index]; check(*context.connection, "alloc output var desc dynamic", OracleSQL_driver->OCIDescriptorAlloc( (dvoid *) context.connection->envhp, (dvoid **)&var.locator, @@ -1113,11 +1253,11 @@ static sb4 cbf_get_data(dvoid *ctxp, return OCI_CONTINUE; } -void tolower(char *out, const char *in, size_t size) { +static void tolower_str(char *out, const char *in, size_t size) { while(size--) *out++=(char)tolower(*in++); } -void toupper(char *out, const char *in, size_t size) { +static void toupper_str(char *out, const char *in, size_t size) { while(size--) *out++=(char)toupper(*in++); }