Diff for /sql/oracle/parser3oracle.C between versions 1.39 and 1.54

version 1.39, 2003/10/28 15:41:01 version 1.54, 2004/03/26 13:26:41
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
   
   #if _MSC_VER
   // interaction between '_setjmp' and C++ object destruction is non-portable
   // but we forced to do that under HPUX
   #pragma warning(disable:4611)   
   #endif
   
 /// @todo small memory leaks here  /// @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;
Line 104  static char *lsplit(char **string_ref, c Line 110  static char *lsplit(char **string_ref, c
     return result;      return result;
 }  }
   
 static const char *options2env(char *options, bool* LowerCaseColumnNames) {  
         while(options) {  
                 if(char *key=lsplit(&options, '&')) {  
                         if(*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+=  
                                         if(do_append)  
                                                 key[strlen(key)-1]=0; // remove trailing +  
                                         if(strncmp(key, "ORACLE_", 7)==0  // ORACLE_HOME & co  
                                                 || strncmp(key, "ORA_", 4)==0 // ORA_ENCRYPT_LOGIN & co  
                                                 || strncmp(key, "NLS_", 4)==0 // NLS_LANG & co  
                                                 || do_append  
                                                 ) {  
                                                 if(pa_setenv(key, value, do_append)!=0)  
                                                         return "problem changing process environment" /*key*/;  
                                         } else  
                                                 return "unknown option (option must start with ORACLE_, ORA_ or NLS_)" /*key*/;  
                                 } else   
                                         return "option without =value" /*key*/;  
                         }  
                 }  
         }  
         return 0;  
 }  
   
 #ifndef DOXYGEN  #ifndef DOXYGEN
 struct OracleSQL_connection_struct {  struct Connection {
           SQL_Driver_services *services;
   
         jmp_buf mark; char error[MAX_STRING];          jmp_buf mark; char error[MAX_STRING];
         SQL_Error sql_error;          SQL_Error sql_error;
         OCIEnv *envhp;          OCIEnv *envhp;
Line 145  struct OracleSQL_connection_struct { Line 122  struct OracleSQL_connection_struct {
         OCISvcCtx *svchp;          OCISvcCtx *svchp;
         OCISession *usrhp;          OCISession *usrhp;
   
         bool bLowerCaseColumnNames;          char* fetch_buffers[MAX_COLS];
   
           struct Options {
                   bool bLowerCaseColumnNames;
                   const char* cstrClientCharset;
           } options;
 };  };
   
 struct OracleSQL_query_lobs {  struct OracleSQL_query_lobs {
Line 158  struct OracleSQL_query_lobs { Line 140  struct OracleSQL_query_lobs {
                 int count;                  int count;
         };          };
         struct cbf_context_struct {          struct cbf_context_struct {
                 SQL_Driver_services *services;                  Connection *connection;
                 OracleSQL_connection_struct *cs;  
                 return_rows *rows;                  return_rows *rows;
         };          };
         struct Item {          struct Item {
Line 174  struct OracleSQL_query_lobs { Line 155  struct OracleSQL_query_lobs {
 #endif  #endif
   
 // forwards  // forwards
 void check(OracleSQL_connection_struct &cs, const char *step, sword status);  void check(Connection& connection, const char *step, sword status);
 void check(OracleSQL_connection_struct &cs, bool error);  void check(Connection& connection, bool error);
 static sb4 cbf_no_data(  static sb4 cbf_no_data(
                                            dvoid *ctxp,                                              dvoid *ctxp, 
                                            OCIBind *bindp,                                              OCIBind *bindp, 
Line 192  static sb4 cbf_get_data(dvoid *ctxp, Line 173  static sb4 cbf_get_data(dvoid *ctxp,
                                                 ub1 *piecep,                                                   ub1 *piecep, 
                                                 dvoid **indpp,                                                   dvoid **indpp, 
                                                 ub2 **rcodepp);                                                  ub2 **rcodepp);
 void tolower(char *out, const char *in, size_t size);  static void tolower(char *out, const char *in, size_t size);
   static void toupper(char *out, const char *in, size_t size);
   
   static const char *options2env(char *s, Connection::Options* options) {
           while(s) {
                   if(char *key=lsplit(&s, '&')) {
                           if(*key) {
                                   if(char *value=lsplit(key, '=')) {
                                           if( strcmp( key, "ClientCharset" ) == 0 ) {
                                                   if(options) {
                                                           toupper(value, value, strlen(value));
                                                           options->cstrClientCharset = value;
                                                   }
                                                   continue;
                                           }
   
                                           if( strcmp( key, "LowerCaseColumnNames" ) == 0 ) {
                                                   if(options)
                                                           options->bLowerCaseColumnNames = atoi(value)!=0;
                                                   continue;
                                           }
   
                                           bool do_append=key[strlen(key)-1]=='+'; // PATH+=
                                           if(do_append)
                                                   key[strlen(key)-1]=0; // remove trailing +
                                           if(strncmp(key, "ORACLE_", 7)==0  // ORACLE_HOME & co
                                                   || strncmp(key, "ORA_", 4)==0 // ORA_ENCRYPT_LOGIN & co
                                                   || strncmp(key, "NLS_", 4)==0 // NLS_LANG & co
                                                   || do_append
                                                   ) {
                                                   if(pa_setenv(key, value, do_append)!=0)
                                                           return "problem changing process environment" /*key*/;
                                           } else
                                                   return "unknown option" /*key*/;
                                   } else 
                                           return "option without =value" /*key*/;
                           }
                   }
           }
           return 0;
   }
   
 /**  /**
         OracleSQL server driver          OracleSQL server driver
Line 240  public: Line 261  public:
         void connect(          void connect(
                 char *used_only_in_connect_url,                   char *used_only_in_connect_url, 
                 SQL_Driver_services& services,                   SQL_Driver_services& services, 
                 void **connection ///< output: OracleSQL_connection_struct *                  void **connection_ref ///< output: Connection *
                 ) {                  ) {
                 // connections are cross-request, do not use services._alloc [linked with request]                  Connection& connection=*(Connection  *)services.malloc(sizeof(Connection));
                 OracleSQL_connection_struct &cs=                  connection.services=&services;
                         *(OracleSQL_connection_struct  *)::calloc(sizeof(OracleSQL_connection_struct), 1);                  connection.options.bLowerCaseColumnNames = true;
                 cs.bLowerCaseColumnNames = true;                  *connection_ref=&connection;
   
                 char *user=used_only_in_connect_url;                  char *user=used_only_in_connect_url;
                 char *service=lsplit(user, '@');                  char *service=lsplit(user, '@');
Line 255  public: Line 276  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, &cs.bLowerCaseColumnNames))                  if(const char *error=options2env(options, &connection.options))
                         services._throw(error);                          services._throw(error);
   
                 if(setjmp(cs.mark))                  if(setjmp(connection.mark))
                         services._throw(cs.error);                          services._throw(connection.error);
   
                 // Allocate and initialize OCIError handle, attempt #1                  // Allocate and initialize OCIError handle, attempt #1
                 /*                  /*
Line 277  public: Line 298  public:
                         think, this is some sort of backward compatibility wonder.                          think, this is some sort of backward compatibility wonder.
                         leaving as it is, and without check()                          leaving as it is, and without check()
                 */                  */
                 OCIHandleAlloc((dvoid *)NULL, (dvoid **) &cs.envhp, (ub4)OCI_HTYPE_ENV, 0, 0);                  OCIHandleAlloc((dvoid *)NULL, (dvoid **) &connection.envhp, (ub4)OCI_HTYPE_ENV, 0, 0);
                 // Initialize an environment handle, attempt #2                  // Initialize an environment handle, attempt #2
                 check(cs, "EnvInit", OCIEnvInit(                  check(connection, "EnvInit", OCIEnvInit(
                         &cs.envhp, (ub4)OCI_DEFAULT, 0, 0));                                      &connection.envhp, (ub4)OCI_DEFAULT, 0, 0));            
                 // Allocate and initialize OCIError handle                  // Allocate and initialize OCIError handle
                 check(cs, "HandleAlloc errhp", OCIHandleAlloc(                   check(connection, "HandleAlloc errhp", OCIHandleAlloc( 
                         (dvoid *)cs.envhp, (dvoid **) &cs.errhp, (ub4)OCI_HTYPE_ERROR, 0, 0));                          (dvoid *)connection.envhp, (dvoid **) &connection.errhp, (ub4)OCI_HTYPE_ERROR, 0, 0));
                 // Allocate and initialize OCIServer handle                  // Allocate and initialize OCIServer handle
                 check(cs, "HandleAlloc srvhp", OCIHandleAlloc(                   check(connection, "HandleAlloc srvhp", OCIHandleAlloc( 
                         (dvoid *)cs.envhp, (dvoid **) &cs.srvhp, (ub4)OCI_HTYPE_SERVER, 0, 0));                                   (dvoid *)connection.envhp, (dvoid **) &connection.srvhp, (ub4)OCI_HTYPE_SERVER, 0, 0));         
                 // Attach to a 'service'; initialize server context handle                    // Attach to a 'service'; initialize server context handle  
                 check(cs, "ServerAttach", OCIServerAttach(                   check(connection, "ServerAttach", OCIServerAttach( 
                         cs.srvhp, cs.errhp, (text *)service, (sb4)strlen(service), (ub4)OCI_DEFAULT));                          connection.srvhp, connection.errhp, (text *)service, (sb4)strlen(service), (ub4)OCI_DEFAULT));
                 // Allocate and initialize OCISvcCtx handle                  // Allocate and initialize OCISvcCtx handle
                 check(cs, "HandleAlloc svchp", OCIHandleAlloc(                   check(connection, "HandleAlloc svchp", OCIHandleAlloc( 
                         (dvoid *)cs.envhp, (dvoid **) &cs.svchp, (ub4)OCI_HTYPE_SVCCTX, 0, 0));                                   (dvoid *)connection.envhp, (dvoid **) &connection.svchp, (ub4)OCI_HTYPE_SVCCTX, 0, 0));         
                 // set attribute server context in the service context                  // set attribute server context in the service context
                 check(cs, "AttrSet server-service", OCIAttrSet(                   check(connection, "AttrSet server-service", OCIAttrSet( 
                         (dvoid *)cs.svchp, (ub4)OCI_HTYPE_SVCCTX,                           (dvoid *)connection.svchp, (ub4)OCI_HTYPE_SVCCTX, 
                         (dvoid *)cs.srvhp, (ub4)0,                           (dvoid *)connection.srvhp, (ub4)0, 
                         (ub4)OCI_ATTR_SERVER, (OCIError *)cs.errhp));                                     (ub4)OCI_ATTR_SERVER, (OCIError *)connection.errhp));           
                 // allocate a user context handle                  // allocate a user context handle
                 check(cs, "HandleAlloc usrhp", OCIHandleAlloc(                  check(connection, "HandleAlloc usrhp", OCIHandleAlloc(
                         (dvoid *)cs.envhp, (dvoid **)&cs.usrhp, (ub4)OCI_HTYPE_SESSION, 0, 0));                          (dvoid *)connection.envhp, (dvoid **)&connection.usrhp, (ub4)OCI_HTYPE_SESSION, 0, 0));
                 // set 'user' name                  // set 'user' name
                 check(cs, "AttrSet user-session", OCIAttrSet(                  check(connection, "AttrSet user-session", OCIAttrSet(
                         (dvoid *)cs.usrhp, (ub4)OCI_HTYPE_SESSION,                           (dvoid *)connection.usrhp, (ub4)OCI_HTYPE_SESSION, 
                         (dvoid *)user, (ub4)strlen(user),                           (dvoid *)user, (ub4)strlen(user), 
                         OCI_ATTR_USERNAME, cs.errhp));                                    OCI_ATTR_USERNAME, connection.errhp));          
                 // set 'pwd' password                  // set 'pwd' password
                 check(cs, "AttrSet pwd-session", OCIAttrSet(                  check(connection, "AttrSet pwd-session", OCIAttrSet(
                         (dvoid *)cs.usrhp, (ub4)OCI_HTYPE_SESSION,                           (dvoid *)connection.usrhp, (ub4)OCI_HTYPE_SESSION, 
                         (dvoid *)pwd, (ub4)strlen(pwd),                           (dvoid *)pwd, (ub4)strlen(pwd), 
                         OCI_ATTR_PASSWORD, cs.errhp));                          OCI_ATTR_PASSWORD, connection.errhp));
                 // Authenticate a user                    // Authenticate a user  
                 check(cs, "SessionBegin", OCISessionBegin(                  check(connection, "SessionBegin", OCISessionBegin(
                         cs.svchp, cs.errhp, cs.usrhp,                           connection.svchp, connection.errhp, connection.usrhp, 
                         OCI_CRED_RDBMS, OCI_DEFAULT));                          OCI_CRED_RDBMS, OCI_DEFAULT));
                 // remember connection in session                  // remember connection in session
                 check(cs, "AttrSet service-session", OCIAttrSet(                  check(connection, "AttrSet service-session", OCIAttrSet(
                         (dvoid *)cs.svchp, (ub4)OCI_HTYPE_SVCCTX,                           (dvoid *)connection.svchp, (ub4)OCI_HTYPE_SVCCTX, 
                         (dvoid *)cs.usrhp, (ub4)0,                           (dvoid *)connection.usrhp, (ub4)0, 
                         OCI_ATTR_SESSION, cs.errhp));                          OCI_ATTR_SESSION, connection.errhp));
   
                 // return created connection  
                 *(OracleSQL_connection_struct **)connection=&cs;  
         }          }
         void disconnect(void *connection) {          void disconnect(void *aconnection) {
             OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;              Connection& connection=*static_cast<Connection *>(aconnection);
   
                   // free fetch buffers
                   for(int i=0; i<MAX_COLS; i++) {
                           if(void* fetch_buffer=connection.fetch_buffers[i])
                                   ::free(fetch_buffer);
                           else
                                   break;
                   }                       
   
                 // Terminate a user session                  // Terminate a user session
                 OCISessionEnd(                  OCISessionEnd(
                         cs.svchp, cs.errhp, cs.usrhp, (ub4)OCI_DEFAULT);                          connection.svchp, connection.errhp, connection.usrhp, (ub4)OCI_DEFAULT);
                 // Detach from a server; uninitialize server context handle                  // Detach from a server; uninitialize server context handle
                 OCIServerDetach(                  OCIServerDetach(
                         cs.srvhp, cs.errhp, (ub4)OCI_DEFAULT);                          connection.srvhp, connection.errhp, (ub4)OCI_DEFAULT);
                 // Free a previously allocated handles                  // Free a previously allocated handles
                 /*                   /* 
                 oci will free them up as belonging to env                  oci will free them up as belonging to env
                 OCIHandleFree(                  OCIHandleFree(
                         (dvoid *)cs.srvhp, (ub4)OCI_HTYPE_SERVER);                          (dvoid *)connection.srvhp, (ub4)OCI_HTYPE_SERVER);
                 OCIHandleFree(                  OCIHandleFree(
                         (dvoid *)cs.svchp, (ub4)OCI_HTYPE_SVCCTX);                          (dvoid *)connection.svchp, (ub4)OCI_HTYPE_SVCCTX);
                 OCIHandleFree(                  OCIHandleFree(
                         (dvoid *)cs.errhp, (ub4)OCI_HTYPE_ERROR);                          (dvoid *)connection.errhp, (ub4)OCI_HTYPE_ERROR);
                 */                  */
                 OCIHandleFree(                  OCIHandleFree(
                         (dvoid *)cs.envhp, (ub4)OCI_HTYPE_ENV);                          (dvoid *)connection.envhp, (ub4)OCI_HTYPE_ENV);
   
                 // connections are cross-request, do not use services._alloc [linked with request]                  // connections are cross-request, do not use services._alloc [linked with request]
                 ::free(&cs);                  ::free(&connection);
         }          }
         void commit(SQL_Driver_services& services, void *connection) {          void commit(void *aconnection) {
             OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;              Connection& connection=*static_cast<Connection *>(aconnection);
                 if(setjmp(cs.mark))                  if(setjmp(connection.mark))
                         services._throw(cs.error);                          connection.services->_throw(connection.error);
   
                 check(cs, "commit", OCITransCommit(cs.svchp, cs.errhp, 0));                  check(connection, "commit", OCITransCommit(connection.svchp, connection.errhp, 0));
         }          }
         void rollback(SQL_Driver_services& services, void *connection) {          void rollback(void *aconnection) {
             OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;              Connection& connection=*static_cast<Connection *>(aconnection);
                 if(setjmp(cs.mark))                  if(setjmp(connection.mark))
                         services._throw(cs.error);                          connection.services->_throw(connection.error);
   
                 check(cs, "rollback", OCITransRollback(cs.svchp, cs.errhp, 0));                  // sometimes rollback is done in context when this yields error which masks previous error
                   // consider consequent errors not very important to report, reporting first one
                   /*check(connection, "rollback", */OCITransRollback(connection.svchp, connection.errhp, 0)/*)*/;
         }          }
   
         bool ping(SQL_Driver_services&, void *connection) {          bool ping(void* /*connection*/) {
                 // maybe OCIServerVersion?                  // maybe OCIServerVersion?
                 // select 0 from dual                  // select 0 from dual
                 return true;                  return true;
         }          }
   
         const char* quote(          const char* quote(void *aconnection,
                 SQL_Driver_services& services, void *connection,                  const char *from, unsigned int length) 
                 const char *from, unsigned int length) {          {
                 char *result=(char*)services.malloc_atomic(length*2+1);                  Connection& connection=*static_cast<Connection *>(aconnection);
                   char *result=(char*)connection.services->malloc_atomic(length*2+1);
                 char *to=result;                  char *to=result;
                 while(length--) {                  while(length--) {
                         switch(*from) {                          switch(*from) {
Line 385  public: Line 415  public:
                 *to=0;                  *to=0;
                 return result;                  return result;
         }          }
         void query(          void query(void *aconnection, 
                 SQL_Driver_services& services, void *connection,   
                 const char *astatement, unsigned long offset, unsigned long limit,                   const char *astatement, unsigned long offset, unsigned long limit, 
                 SQL_Driver_query_event_handlers& handlers) {                  SQL_Driver_query_event_handlers& handlers) 
                           {
                 OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;                  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;
   
                   // transcode from $request:charset to connect-string?client_charset
                   if(cstrClientCharset) {
                           size_t transcoded_statement_size;
                           services.transcode(astatement, strlen(astatement),
                                   astatement, transcoded_statement_size,
                                   services.request_charset(),
                                   cstrClientCharset);
                   }
   
                 bool failed=false;                  bool failed=false;
                 if(setjmp(cs.mark)) {                  if(setjmp(connection.mark)) {
                         failed=true;                          failed=true;
                         goto cleanup;                          goto cleanup;
                 } else {                  } else {
                         const char *statement=preprocess_statement(services, cs,                           const char *statement=preprocess_statement(connection, astatement, lobs);
                                 astatement, lobs);  
   
                         check(cs, "HandleAlloc STMT", OCIHandleAlloc(                           check(connection, "HandleAlloc STMT", OCIHandleAlloc( 
                                 (dvoid *)cs.envhp, (dvoid **) &stmthp, (ub4)OCI_HTYPE_STMT, 0, 0));                                  (dvoid *)connection.envhp, (dvoid **) &stmthp, (ub4)OCI_HTYPE_STMT, 0, 0));
                         check(cs, "syntax",                           check(connection, "syntax", 
                                 OCIStmtPrepare(stmthp, cs.errhp, (unsigned char *)statement,                                   OCIStmtPrepare(stmthp, connection.errhp, (unsigned char *)statement, 
                                 (ub4)strlen((char *)statement),                                   (ub4)strlen((char *)statement), 
                                 (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++) {
                                         check(cs, "alloc output var desc", OCIDescriptorAlloc(                                          check(connection, "alloc output var desc", OCIDescriptorAlloc(
                                                 (dvoid *)cs.envhp, (dvoid **)&lobs.items[i].locator, (ub4)OCI_DTYPE_LOB, 0, 0));                                                  (dvoid *)connection.envhp, (dvoid **)&lobs.items[i].locator, (ub4)OCI_DTYPE_LOB, 0, 0));
   
                                         check(cs, "bind output", OCIBindByPos(stmthp,                                           check(connection, "bind output", OCIBindByPos(stmthp, 
                                                 &lobs.items[i].bind, cs.errhp,                                                   &lobs.items[i].bind, connection.errhp, 
                                                 (ub4)1+i,                                                   (ub4)1+i, 
                                                 (dvoid *)&lobs.items[i].locator,                                                   (dvoid *)&lobs.items[i].locator, 
                                                 (sword)sizeof (lobs.items[i].locator), SQLT_CLOB, (dvoid *)0,                                                   (sword)sizeof (lobs.items[i].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;                                          lobs.items[i].rows.count=0;
                                         OracleSQL_query_lobs::cbf_context_struct cbf_context={                                          OracleSQL_query_lobs::cbf_context_struct cbf_context={&connection, &lobs.items[i].rows};
                                                 &services, &cs, &lobs.items[i].rows};                                          check(connection, "bind dynamic", OCIBindDynamic(
                                         check(cs, "bind dynamic", OCIBindDynamic(                                                  lobs.items[i].bind, connection.errhp, 
                                                 lobs.items[i].bind, cs.errhp,   
                                                 (dvoid *) &cbf_context, cbf_no_data,                                                   (dvoid *) &cbf_context, cbf_no_data, 
                                                 (dvoid *) &cbf_context, cbf_get_data));                                                  (dvoid *) &cbf_context, cbf_get_data));
                                 }                                  }
                         }                          }
   
                         execute_prepared(services, cs,                           execute_prepared(connection, 
                                 statement, stmthp, lobs,                                   statement, stmthp, lobs, 
                                 offset, limit, handlers);                                  offset, limit, handlers);
                 }                  }
Line 451  cleanup: // no check call after this poi Line 490  cleanup: // no check call after this poi
                         OCIHandleFree((dvoid *)stmthp, (ub4)OCI_HTYPE_STMT);                          OCIHandleFree((dvoid *)stmthp, (ub4)OCI_HTYPE_STMT);
   
                 if(failed) {                  if(failed) {
                         if(cs.sql_error.defined())                          if(connection.sql_error.defined())
                                 services._throw(cs.sql_error);                                  services._throw(connection.sql_error);
                         services._throw(cs.error);                          services._throw(connection.error);
                 }                  }
         }          }
   
 private: // private funcs  private: // private funcs
   
         const char *preprocess_statement(SQL_Driver_services& services, OracleSQL_connection_struct &cs,           const char *preprocess_statement(Connection& connection, 
                 const char *astatement, OracleSQL_query_lobs &lobs) {                  const char *astatement, OracleSQL_query_lobs &lobs) {
                 size_t statement_size=strlen(astatement);                  size_t statement_size=strlen(astatement);
                   SQL_Driver_services& services=*connection.services;
   
                 char *result=(char *)services.malloc_atomic(statement_size                  char *result=(char *)services.malloc_atomic(statement_size
                         +MAX_STRING // in case of short 'strings'                          +MAX_STRING // in case of short 'strings'
Line 533  private: // private funcs Line 573  private: // private funcs
                                 if(i)                                  if(i)
                                         *n++=',';                                          *n++=',';
                                 n+=sprintf(n, "%.*s", lobs.items[i].name_size, lobs.items[i].name_ptr);                                  n+=sprintf(n, "%.*s", lobs.items[i].name_size, lobs.items[i].name_ptr);
                                 /*memcpy(n, lobs.items[i].name_ptr, lobs.items[i].name_size);  
                                 n+=lobs.items[i].name_size;*/  
                         }                          }
                         n+=sprintf(n, " into ");                          n+=sprintf(n, " into ");
                         for(i=0; i<lobs.count; i++) {                          for(i=0; i<lobs.count; i++) {
                                 if(i)                                  if(i)
                                         *n++='x';                                          *n++=',';
                                 n+=sprintf(n, ":%.*s", lobs.items[i].name_size, lobs.items[i].name_ptr);                                  n+=sprintf(n, ":%.*s", lobs.items[i].name_size, lobs.items[i].name_ptr);
                                 /**n++=':';  
                                 memcpy(n, lobs.items[i].name_ptr, lobs.items[i].name_size);  
                                 n+=lobs.items[i].name_size;*/  
                         }                          }
                 }                  }
   
Line 551  private: // private funcs Line 586  private: // private funcs
         }          }
   
         void execute_prepared(          void execute_prepared(
                 SQL_Driver_services& services, OracleSQL_connection_struct &cs,                   Connection& connection, 
                 const char *statement, OCIStmt *stmthp, OracleSQL_query_lobs &lobs,                   const char *statement, OCIStmt *stmthp, OracleSQL_query_lobs &lobs, 
                 unsigned long offset, unsigned long limit,                   unsigned long offset, unsigned long limit, 
                 SQL_Driver_query_event_handlers& handlers) {                  SQL_Driver_query_event_handlers& handlers) {
Line 560  private: // private funcs Line 595  private: // private funcs
         /*          /*
                 //gpfs on sun. paf 000818                  //gpfs on sun. paf 000818
                 //Zanyway, this is needed before.                   //Zanyway, this is needed before. 
                 check(cs, "get stmt type", OCIAttrGet(                  check(connection, "get stmt type", OCIAttrGet(
                         (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT, (ub1 *)&stmt_type,                           (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT, (ub1 *)&stmt_type, 
                         (ub4 *)0, OCI_ATTR_STMT_TYPE, cs.errhp));                          (ub4 *)0, OCI_ATTR_STMT_TYPE, connection.errhp));
         */          */
   
                 while(isspace(*statement))                   while(isspace(*statement)) 
Line 574  private: // private funcs Line 609  private: // private funcs
                 else if(strncasecmp(statement, "update", 6)==0)                  else if(strncasecmp(statement, "update", 6)==0)
                         stmt_type=OCI_STMT_UPDATE;                          stmt_type=OCI_STMT_UPDATE;
   
                 sword status=OCIStmtExecute(cs.svchp, stmthp, cs.errhp,                   sword status=OCIStmtExecute(connection.svchp, stmthp, connection.errhp, 
                         (ub4)stmt_type==OCI_STMT_SELECT?0:1, (ub4)0,                           (ub4)stmt_type==OCI_STMT_SELECT?0:1, (ub4)0, 
                         (OCISnapshot *)NULL,                           (OCISnapshot *)NULL, 
                         (OCISnapshot *)NULL, (ub4)OCI_DEFAULT);                          (OCISnapshot *)NULL, (ub4)OCI_DEFAULT);
   
                 if(status!=OCI_NO_DATA)                  if(status!=OCI_NO_DATA)
                         check(cs, "execute", status);                          check(connection, "execute", status);
   
                 {                  {
                         for(int i=0; i<lobs.count; i++)                           for(int i=0; i<lobs.count; i++) 
Line 588  private: // private funcs Line 623  private: // private funcs
                                         OracleSQL_query_lobs::return_rows *rows=&lobs.items[i].rows;                                          OracleSQL_query_lobs::return_rows *rows=&lobs.items[i].rows;
                                         for(int r=0; r<rows->count; r++) {                                          for(int r=0; r<rows->count; r++) {
                                                 OCILobLocator *locator=rows->row[r].locator;                                                  OCILobLocator *locator=rows->row[r].locator;
                                                 check(cs, "lobwrite", OCILobWrite (                                                  check(connection, "lobwrite", OCILobWrite (
                                                         cs.svchp, cs.errhp,                                                           connection.svchp, connection.errhp, 
                                                         locator, &bytes_to_write, 1,                                                           locator, &bytes_to_write, 1, 
                                                         (dvoid *)lobs.items[i].data_ptr, (ub4)bytes_to_write, OCI_ONE_PIECE,                                                           (dvoid *)lobs.items[i].data_ptr, (ub4)bytes_to_write, OCI_ONE_PIECE, 
                                                         (dvoid *)0, 0, (ub2)0,                                                           (dvoid *)0, 0, (ub2)0, 
Line 600  private: // private funcs Line 635  private: // private funcs
                                   
                 switch(stmt_type) {                  switch(stmt_type) {
                 case OCI_STMT_SELECT:                  case OCI_STMT_SELECT:
                         fetch_table(services, cs,                          fetch_table(connection,
                                 stmthp, offset, limit,                                   stmthp, offset, limit, 
                                 handlers);                                  handlers);
                         break;                          break;
Line 613  private: // private funcs Line 648  private: // private funcs
                 }                  }
         }          }
   
         void fetch_table(SQL_Driver_services& services, OracleSQL_connection_struct &cs,           void fetch_table(Connection& connection, 
                 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;
   
                 ub4 prefetch_rows=100;                  ub4 prefetch_rows=100;
                 check(cs, "AttrSet prefetch-rows", OCIAttrSet(                   check(connection, "AttrSet prefetch-rows", OCIAttrSet( 
                         (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT,                           (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT, 
                         (dvoid *)&prefetch_rows, (ub4)0,                           (dvoid *)&prefetch_rows, (ub4)0, 
                         (ub4)OCI_ATTR_PREFETCH_ROWS, (OCIError *)cs.errhp));                          (ub4)OCI_ATTR_PREFETCH_ROWS, (OCIError *)connection.errhp));
   
                 ub4 prefetch_mem_size=100*0x400;                  ub4 prefetch_mem_size=100*0x400;
                 check(cs, "AttrSet prefetch-memory", OCIAttrSet(                   check(connection, "AttrSet prefetch-memory", OCIAttrSet( 
                         (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT,                           (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT, 
                         (dvoid *)&prefetch_mem_size, (ub4)0,                           (dvoid *)&prefetch_mem_size, (ub4)0, 
                         (ub4)OCI_ATTR_PREFETCH_MEMORY, (OCIError *)cs.errhp));                          (ub4)OCI_ATTR_PREFETCH_MEMORY, (OCIError *)connection.errhp));
   
                 OCIParam          *mypard;                  OCIParam          *mypard;
                 ub2                    dtype;                  ub2                    dtype;
                 text                  *col_name;                  const char*           col_name;
   
                 struct {                  struct Col {
                         ub2 type;                          ub2 type;
                         char *str;                          char *str;
                         OCILobLocator *var;                          OCILobLocator *var;
Line 643  private: // private funcs Line 681  private: // private funcs
                 int column_count=0;                  int column_count=0;
   
                 bool failed=false;                  bool failed=false;
                 jmp_buf saved_mark; memcpy(saved_mark, cs.mark, sizeof(jmp_buf));                  jmp_buf saved_mark; memcpy(saved_mark, connection.mark, sizeof(jmp_buf));
                 if(setjmp(cs.mark)) {                  if(setjmp(connection.mark)) {
                         failed=true;                          failed=true;
                         goto cleanup;                          goto cleanup;
                 } else {                  } else {
                         // idea of preincrementing is that at error time all handles would free up                          // idea of preincrementing is that at error time all handles would free up
                         while(++column_count<=MAX_COLS) {                          while(++column_count<=MAX_COLS) {
                                 /* get next descriptor, if there is one */                                  /* get next descriptor, if there is one */
                                 if(OCIParamGet(stmthp, OCI_HTYPE_STMT, cs.errhp, (void **)&mypard,                                   if(OCIParamGet(stmthp, OCI_HTYPE_STMT, connection.errhp, (void **)&mypard, 
                                         (ub4) column_count)!=OCI_SUCCESS) {                                          (ub4) column_count)!=OCI_SUCCESS) {
                                         --column_count;                                          --column_count;
                                         break;                                          break;
                                 }                                  }
                                                                   
                                 /* Retrieve the data type attribute */                                  /* Retrieve the data type attribute */
                                 check(cs, "get type", OCIAttrGet(                                  check(connection, "get type", OCIAttrGet(
                                         (dvoid*) mypard, (ub4)OCI_DTYPE_PARAM,                                           (dvoid*) mypard, (ub4)OCI_DTYPE_PARAM, 
                                         (dvoid*) &dtype, (ub4 *)0, (ub4)OCI_ATTR_DATA_TYPE,                                           (dvoid*) &dtype, (ub4 *)0, (ub4)OCI_ATTR_DATA_TYPE, 
                                         (OCIError *)cs.errhp));                                          (OCIError *)connection.errhp));
                                                                   
                                 /* Retrieve the column name attribute */                                  /* Retrieve the column name attribute */
                                 ub4 col_name_len;                                  ub4 col_name_len;
                                 check(cs, "get name", OCIAttrGet(                                  check(connection, "get name", OCIAttrGet(
                                         (dvoid*) mypard, (ub4)OCI_DTYPE_PARAM,                                           (dvoid*) mypard, (ub4)OCI_DTYPE_PARAM, 
                                         (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 *)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;                                          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( cs.bLowerCaseColumnNames )                                           if( connection.options.bLowerCaseColumnNames ) 
                                                 tolower(ptr, (char *)col_name, length);                                                  tolower(ptr, col_name, length);
                                         else                                          else
                                                 memcpy(ptr, col_name, length);                                                                                            memcpy(ptr, col_name, length);                                          
                                         ptr[length]=0;                                          ptr[length]=0;
                                         check(cs, handlers.add_column(cs.sql_error, ptr, length));                                          check(connection, handlers.add_column(connection.sql_error, ptr, length));
                                 }                                  }
                                                                   
                                 ub2 coerce_type=dtype;                                  ub2 coerce_type=dtype;
Line 688  private: // private funcs Line 734  private: // private funcs
                                 switch(dtype) {                                  switch(dtype) {
                                 case SQLT_CLOB:                                   case SQLT_CLOB: 
                                         {                                          {
                                                 check(cs, "alloc output var desc", OCIDescriptorAlloc(                                                  check(connection, "alloc output var desc", OCIDescriptorAlloc(
                                                         (dvoid *)cs.envhp, (dvoid **)(ptr=&cols[column_count-1].var),                                                           (dvoid *)connection.envhp, (dvoid **)(ptr=&col.var), 
                                                         (ub4)OCI_DTYPE_LOB,                                                           (ub4)OCI_DTYPE_LOB, 
                                                         0, (dvoid **)0));                                                          0, (dvoid **)0));
                                                                                                   
Line 698  private: // private funcs Line 744  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);                                          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*/);
                                           col.str=(char*)ptr;
                                         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(                                  // http://i/docs/oracle/server.804/a58234/oci_func.htm#449680
                                         stmthp, &cols[column_count-1].def, cs.errhp,                                   //   this call implicitly allocates the define handle
                                   // http://sunsite.eunnet.net/documentation/oracle.8.0.4/server.804/a58234/basics.htm
                                   //   when a statement handle is freed, any bind and define handles associated with it 
                                   //   are also freed
                                   col.def=0; check(connection, "DefineByPos", OCIDefineByPos(
                                           stmthp, &col.def, connection.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));
                         }                          }
                                                   
                         check(cs, handlers.before_rows(cs.sql_error));                          check(connection, handlers.before_rows(connection.sql_error));
                                                   
                         for(unsigned long row=0; !limit||row<offset+limit; row++) {                          for(unsigned long row=0; !limit||row<offset+limit; row++) {
                                 sword status=OCIStmtFetch(stmthp, cs.errhp, (ub4)1,  (ub4)OCI_FETCH_NEXT,                                   sword status=OCIStmtFetch(stmthp, connection.errhp, (ub4)1,  (ub4)OCI_FETCH_NEXT, 
                                         (ub4)OCI_DEFAULT);                                          (ub4)OCI_DEFAULT);
                                 if(status==OCI_NO_DATA)                                  if(status==OCI_NO_DATA)
                                         break;                                          break;
                                 check(cs, "fetch", status);                                  check(connection, "fetch", status);
   
                                 if(row>=offset) {                                  if(row>=offset) {
                                         check(cs, handlers.add_row(cs.sql_error));                                          check(connection, handlers.add_row(connection.sql_error));
                                         for(int i=0; i<column_count; i++) {                                          for(int i=0; i<column_count; i++) {
                                                 size_t length=0;                                                  size_t length=0;
                                                 char* str=0;                                                  char* strm=0;
                                                 if(!cols[i].indicator) // not NULL                                                  if(!cols[i].indicator) // not NULL
                                                         switch(cols[i].type) {                                                          switch(cols[i].type) {
                                                         case SQLT_CLOB:                                                           case SQLT_CLOB: 
                                                                 {                                                                  {
                                                                         ub4   amtp=4096000000UL;  
                                                                         ub4   offset=1;                                                                          ub4   offset=1;
                                                                         ub4   loblen=0;  
                                                                         OCILobLocator *var=(OCILobLocator *)cols[i].var;                                                                          OCILobLocator *var=(OCILobLocator *)cols[i].var;
                                                                         OCILobGetLength(cs.svchp, cs.errhp, var, &loblen);                                                                          size_t read_size=0;
                                                                         if(loblen) {                                                                          strm=(char*)services.malloc_atomic(1/*for terminator*/); // set type of memory block
                                                                                 length=(size_t)loblen;                                                                          do {
                                                                                 str=(char*)services.malloc_atomic(length+1);                                                                                  char buf[MAX_STRING*10];
                                                                                 check(cs, "lobread", OCILobRead(cs.svchp, cs.errhp,                                                                                   ub4   amtp=0/*to be read in stream mode*/;
                                                                                         var, &amtp, offset, (dvoid *) str,                                                                                   // http://i/docs/oracle/server.804/a58234/oci_func.htm#427818
                                                                                         loblen, (dvoid *)0,                                                                                   status=OCILobRead(connection.svchp, connection.errhp, 
                                                                                         0,                                                                                           var, &amtp, offset, (dvoid *)buf, 
                                                                                         (ub2)0, (ub1) SQLCS_IMPLICIT));                                                                                          sizeof(buf), 
                                                                                 str[length]=0;                                                                                          (dvoid *)0, 0, 
                                                                         }                                                                                          (ub2)0, (ub1)SQLCS_IMPLICIT);
                                           if(status!=OCI_SUCCESS && status!=OCI_NEED_DATA)
                                                                                           check(connection, "lobread", status);
   
                                                                                   strm=(char*)services.realloc(strm, read_size+amtp+1/*for termintator*/);
                                                                                   memcpy(strm+read_size, buf, amtp);
                                                                                   read_size+=amtp;
                                                                                   offset+=amtp;
                                                                           } while(status==OCI_NEED_DATA);
   
                                                                           length=(size_t)read_size;
                                                                           strm[length]=0;
                                                                         break;                                                                          break;
                                                                 }                                                                  }
                                                         default:                                                          default:
                                                                 if(const char *value=cols[i].str) {                                                                  if(const char *value=cols[i].str) {
                                                                         length=strlen(value);                                                                          length=strlen(value);
                                                                         str=(char*)services.malloc_atomic(length+1);                                                                          strm=(char*)services.malloc_atomic(length+1);
                                                                         memcpy(str, value, length+1);                                                                          memcpy(strm, value, length+1);
                                                                 } else {                                                                  } else {
                                                                         length=0;                                                                          length=0;
                                                                         str=0;                                                                          strm=0;
                                                                 }                                                                  }
                                                                 break;                                                                  break;
                                                         }                                                          }
                                                 check(cs, handlers.add_row_cell(cs.sql_error, str, length));  
                                                   const char* str=strm;
                                                   if(str && length)
                                                   {
                                                           // transcode to $request:charset from connect-string?client_charset
                                                           if(cstrClientCharset)
                                                                   services.transcode(str, length,
                                                                           str, length,
                                                                           cstrClientCharset,
                                                                           services.request_charset());
                                                   }
   
                                                   check(connection, handlers.add_row_cell(connection.sql_error, str, length));
                                         }                                          }
                                 }                                  }
                         }                          }
Line 782  cleanup: // no check call after this poi Line 858  cleanup: // no check call after this poi
   
 private: // conn client library funcs  private: // conn client library funcs
                   
         friend void check(OracleSQL_connection_struct &cs, const char *step, sword status);          friend void check(Connection& connection, const char *step, sword status);
         friend sb4 cbf_get_data(dvoid *ctxp,           friend sb4 cbf_get_data(dvoid *ctxp, 
                 OCIBind *bindp,                   OCIBind *bindp, 
                 ub4 iter, ub4 index,                   ub4 iter, ub4 index, 
Line 925  private: // conn client library funcs li Line 1001  private: // conn client library funcs li
   
 } *OracleSQL_driver;  } *OracleSQL_driver;
   
 void check(OracleSQL_connection_struct &cs, const char *step, sword status) {  void check(Connection& connection, const char *step, sword status) {
   
         const char *msg;          const char *msg;
         char reason[MAX_STRING/2];          char reason[MAX_STRING/2];
   
         const char *prefix="ERROR";  
         switch (status) {          switch (status) {
         case OCI_SUCCESS: // hurrah          case OCI_SUCCESS: // hurrah
         case OCI_SUCCESS_WITH_INFO:             // ignoring. example: count(column) when column contains NULLs,           case OCI_SUCCESS_WITH_INFO:             // ignoring. example: count(column) when column contains NULLs, 
Line 938  void check(OracleSQL_connection_struct & Line 1013  void check(OracleSQL_connection_struct &
                 return;                  return;
         case OCI_ERROR:          case OCI_ERROR:
                 {                  {
                 sb4 errcode;                          sb4 errcode;
                 if(OracleSQL_driver->OCIErrorGet((dvoid *)cs.errhp, (ub4)1, (text *)NULL, &errcode,                           if(OracleSQL_driver->OCIErrorGet((dvoid *)connection.errhp, (ub4)1, (text *)NULL, &errcode, 
                         (text *)reason, (ub4)sizeof(reason), OCI_HTYPE_ERROR)==OCI_SUCCESS)                                  (text *)reason, (ub4)sizeof(reason), OCI_HTYPE_ERROR)==OCI_SUCCESS) {
                         msg=reason;                                  msg=reason;
                 else  
                         msg="[can not get error description]";                                  // transcode to $request:charset from connect-string?client_charset
                 break;                                  if(const char* cstrClientCharset=connection.options.cstrClientCharset) {
                                           if(msg) {
                                                   if(size_t msg_length=strlen(msg)) {
                                                           connection.services->transcode(msg, msg_length,
                                                                   msg, msg_length,
                                                                   cstrClientCharset,
                                                                   connection.services->request_charset());
                                                   }
                                           }
                                   }
                           } else
                                   msg="[can not get error description]";
                           break;
                 }                  }
         case OCI_NEED_DATA:          case OCI_NEED_DATA:
                 msg="NEED_DATA"; break;                  msg="NEED_DATA"; break;
Line 960  void check(OracleSQL_connection_struct & Line 1047  void check(OracleSQL_connection_struct &
                 msg="unknown"; break;                  msg="unknown"; break;
         }          }
   
         snprintf(cs.error, sizeof(cs.error), "%s (%s, %d)",           snprintf(connection.error, sizeof(connection.error), "%s (%s, %d)", 
                 msg, step, (int)status);                  msg, step, (int)status);
         longjmp(cs.mark, 1);          longjmp(connection.mark, 1);
 }  }
   
 void check(OracleSQL_connection_struct &cs, bool error) {  void check(Connection& connection, bool error) {
         if(error)          if(error)
                 longjmp(cs.mark, 1);                  longjmp(connection.mark, 1);
 }  }
   
 /* ----------------------------------------------------------------- */  /* ----------------------------------------------------------------- */
 /* Intbind callback that does not do any data input.                 */  /* Intbind callback that does not do any data input.                 */
 /* ----------------------------------------------------------------- */  /* ----------------------------------------------------------------- */
 static sb4 cbf_no_data(  static sb4 cbf_no_data(
                                 dvoid *ctxp,                                   dvoid* /*ctxp*/, 
                                 OCIBind *bindp,                                   OCIBind* /*bindp*/, 
                                 ub4 iter, ub4 index,                                   ub4 /*iter*/, ub4 /*index*/, 
                                 dvoid **bufpp,                                   dvoid **bufpp, 
                                 ub4 *alenpp,                                   ub4 *alenpp, 
                                 ub1 *piecep,                                   ub1 *piecep, 
Line 995  static sb4 cbf_no_data( Line 1082  static sb4 cbf_no_data(
 /* ----------------------------------------------------------------- */  /* ----------------------------------------------------------------- */
 static sb4 cbf_get_data(dvoid *ctxp,   static sb4 cbf_get_data(dvoid *ctxp, 
                                  OCIBind *bindp,                                    OCIBind *bindp, 
                                  ub4 iter, ub4 index,                                    ub4 /*iter*/, ub4 index, 
                                  dvoid **bufpp,                                    dvoid **bufpp, 
                                  ub4 **alenp,                                    ub4 **alenp, 
                                  ub1 *piecep,                                    ub1 *piecep, 
Line 1006  static sb4 cbf_get_data(dvoid *ctxp, Line 1093  static sb4 cbf_get_data(dvoid *ctxp,
   
         if(index==0) {          if(index==0) {
                 static ub4  rows;                  static ub4  rows;
                 check(*context.cs, "AttrGet cbf_get_data ROWS_RETURNED",                   check(*context.connection, "AttrGet cbf_get_data ROWS_RETURNED", 
                         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.cs->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.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.cs, "alloc output var desc dynamic", OracleSQL_driver->OCIDescriptorAlloc(          check(*context.connection, "alloc output var desc dynamic", OracleSQL_driver->OCIDescriptorAlloc(
                 (dvoid *) context.cs->envhp, (dvoid **)&var.locator,                   (dvoid *) context.connection->envhp, (dvoid **)&var.locator, 
                 (ub4)OCI_DTYPE_LOB,                   (ub4)OCI_DTYPE_LOB, 
                 0, (dvoid **)0));                  0, (dvoid **)0));
   
Line 1031  static sb4 cbf_get_data(dvoid *ctxp, Line 1118  static sb4 cbf_get_data(dvoid *ctxp,
         return OCI_CONTINUE;          return OCI_CONTINUE;
 }  }
   
 void tolower(char *out, const char *in, size_t size) {  static void tolower(char *out, const char *in, size_t size) {
         while(size--)          while(size--)
                 *out++=tolower(*in++);                  *out++=(char)tolower(*in++);
 }  }
   static void toupper(char *out, const char *in, size_t size) {
           while(size--)
                   *out++=(char)toupper(*in++);
   }
   
   
 extern "C" SQL_Driver *SQL_DRIVER_CREATE() {  extern "C" SQL_Driver *SQL_DRIVER_CREATE() {
         return OracleSQL_driver=new OracleSQL_Driver();          return OracleSQL_driver=new OracleSQL_Driver();

Removed from v.1.39  
changed lines
  Added in v.1.54


E-mail: