Diff for /sql/oracle/parser3oracle.C between versions 1.60 and 1.67

version 1.60, 2004/06/18 15:55:52 version 1.67, 2004/12/23 16:54:52
Line 7 Line 7
   
         2001.07.30 using Oracle 8.1.6 [@test tested with Oracle 7.x.x]          2001.07.30 using Oracle 8.1.6 [@test tested with Oracle 7.x.x]
 */  */
   
 static const char *RCSId="$Id$";   static const char *RCSId="$Id$"; 
   
 #include "config_includes.h"  #include "config_includes.h"
Line 19  static const char *RCSId="$Id$"; Line 20  static const char *RCSId="$Id$";
 #define MAX_IN_LOBS 5  #define MAX_IN_LOBS 5
 #define MAX_LOB_NAME_LENGTH 100  #define MAX_LOB_NAME_LENGTH 100
 #define MAX_OUT_STRING_LENGTH 4000  #define MAX_OUT_STRING_LENGTH 4000
   #define MAX_BINDS 100
   
 #define EMPTY_CLOB_FUNC_CALL "empty_clob()"  #define EMPTY_CLOB_FUNC_CALL "empty_clob()"
   
Line 44  inline int min(int a, int b){ return a<b Line 46  inline int min(int a, int b){ return a<b
 #pragma warning(disable:4611)     #pragma warning(disable:4611)   
 #endif  #endif
   
   const sb2 MAGIC_INDICATOR_VALUE_MEANING_NOT_NULL_AND_UNCHANGED=99;
   
 /// @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 109  static char *lsplit(char **string_ref, c Line 113  static char *lsplit(char **string_ref, c
     return result;      return result;
 }  }
   
   static char* rsplit(char* string, char delim) {
       if(string) {
                   char* v=strrchr(string, delim); 
                   if(v) {
                           *v=0;
                           return v+1;
                   }
       }
       return NULL;        
   }
   
 #ifndef DOXYGEN  #ifndef DOXYGEN
 struct Connection {  struct Connection {
         SQL_Driver_services *services;          SQL_Driver_services *services;
Line 122  struct Connection { Line 137  struct Connection {
         OCISession *usrhp;          OCISession *usrhp;
   
         char* fetch_buffers[MAX_COLS];          char* fetch_buffers[MAX_COLS];
           char* bind_buffers[MAX_BINDS];
   
         struct Options {          struct Options {
                 bool bLowerCaseColumnNames;                  bool bLowerCaseColumnNames;
Line 270  public: Line 286  public:
                 *connection_ref=&connection;                  *connection_ref=&connection;
   
                 char *user=url;                  char *user=url;
                 char *service=lsplit(user, '@');                  char *service=rsplit(user, '@');
                 char *pwd=lsplit(user, ':');                  char *pwd=lsplit(user, ':');
                 char *options=lsplit(service, '?');                  char *options=lsplit(service, '?');
   
Line 424  public: Line 440  public:
                 unsigned long offset, unsigned long limit,                  unsigned long offset, unsigned long limit,
                 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;                  const char* cstrClientCharset=connection.options.cstrClientCharset;
                 Query_lobs lobs={{0}, 0};                  Query_lobs lobs={{0}, 0};
Line 445  public: Line 462  public:
                         failed=true;                          failed=true;
                         goto cleanup;                          goto cleanup;
                 } else {                  } else {
                           if(placeholders_count>MAX_BINDS)
                                   fail(connection, "too many bind variables");
   
                         const char *statement=preprocess_statement(connection, astatement, lobs);                          const char *statement=preprocess_statement(connection, astatement, lobs);
   
                         check(connection, "HandleAlloc STMT", OCIHandleAlloc(                           check(connection, "HandleAlloc STMT", OCIHandleAlloc( 
Line 460  public: Line 480  public:
                         };                          };
   
                         int binds_size=sizeof(Bind_info) * placeholders_count;                          int binds_size=sizeof(Bind_info) * placeholders_count;
                           // we DO store OCIBind* into ATOMIC gc memory, 
                           // but we do not allocate/free it, that's done automatically from oracle [using environment handles]
                           // so we don't have to bother with that
                         Bind_info* binds=static_cast<Bind_info*>(services.malloc_atomic(binds_size));                          Bind_info* binds=static_cast<Bind_info*>(services.malloc_atomic(binds_size));
                         {                          {
                                 for(size_t i=0; i<placeholders_count; i++) {                                  for(size_t i=0; i<placeholders_count; i++) {
                                         Placeholder& ph=placeholders[i];                                          Placeholder& ph=placeholders[i];
                                         Bind_info& bi=binds[i];                                          Bind_info& bi=binds[i];
                                         bi.bind=0;                                          bi.bind=0;
                                         bi.indicator=ph.is_null? -1: 0/*9999*/;                                          // http://i/docs/oracle/server.804/a58234/basics.htm#422173
                                           bi.indicator=ph.is_null? -1: MAGIC_INDICATOR_VALUE_MEANING_NOT_NULL_AND_UNCHANGED;
   
                                         size_t value_length;                                          size_t value_length;
   
Line 486  public: Line 510  public:
                                                 value_length=ph.value? strlen(ph.value): 0;                                                  value_length=ph.value? strlen(ph.value): 0;
                                         }                                          }
   
                                         char placeholder_buf[MAX_STRING];                                          // clone value for possible output binds
                                         sb4 placeh_len=snprintf(placeholder_buf, sizeof(placeholder_buf), ":%s", ph.name);                                          // note: even empty input can be replaced by huge output
                                         check(connection, "bind name", OCIBindByName(stmthp,                                           char*& value_buf=connection.bind_buffers[i]; // get cached buffer
                                           if(!value_buf) // allocate if needed, caching it
                                                   value_buf=(char *)services.malloc_atomic(MAX_OUT_STRING_LENGTH+1/*terminator*/);
                                           if(value_length)
                                                   memcpy(value_buf, ph.value, value_length+1);
                                           else
                                                   value_buf[0]=0;
   
                                           char name_buf[MAX_STRING];
                                           sb4 placeh_len=snprintf(name_buf, sizeof(name_buf), ":%s", ph.name);
                                           char check_step_buf[MAX_STRING];
                                           snprintf(check_step_buf, sizeof(check_step_buf), "bind by name :%s", ph.name);
                                           check(connection, check_step_buf, OCIBindByName(stmthp, 
                                                 &bi.bind, connection.errhp,                                                   &bi.bind, connection.errhp, 
                                                 (text*)placeholder_buf, placeh_len,                                                  (text*)name_buf, placeh_len,
                                                 (dvoid *)ph.value, (sword)value_length, SQLT_CHR/*SQLT_STR*/, (dvoid *)&bi.indicator,                                                   (dvoid *)value_buf, (sword)(MAX_OUT_STRING_LENGTH+1), SQLT_STR, (dvoid *)&bi.indicator, 
                                                 (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, OCI_DEFAULT));                                                  (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, OCI_DEFAULT));
                                 }                                  }
   
Line 525  public: Line 561  public:
   
                         {                          {
                                 for(size_t i=0; i<placeholders_count; i++) {                                  for(size_t i=0; i<placeholders_count; i++) {
                                         Placeholder& ph=placeholders[i];  
                                         Bind_info& bi=binds[i];                                          Bind_info& bi=binds[i];
                                           if(bi.indicator==MAGIC_INDICATOR_VALUE_MEANING_NOT_NULL_AND_UNCHANGED/*unchanged*/)
                                         if(bi.indicator==9999 /*unchanged*/)  
                                                 continue;                                                  continue;
   
                                           Placeholder& ph=placeholders[i];
                                         if(bi.indicator==-1)                                          if(bi.indicator==-1)
                                                 ph.is_null=true;                                                  ph.is_null=true;
                                         else                                          else
Line 538  public: Line 573  public:
                                                         ph.is_null=false;                                                          ph.is_null=false;
                                                 else                                                  else
                                                         fail(connection, bi.indicator<0?                                                          fail(connection, bi.indicator<0?
                                                                 "column return buffer overflow, additionally size too big to be returned in 'indicator'"                                                                  "output bind buffer overflow, additionally size too big to be returned in 'indicator'"
                                                                 : "column return buffer overflow");                                                                  : "output bind buffer overflow");
   
                                         ph.were_updated=true;                                          ph.were_updated=true;
                                           const char* bind_buffer=connection.bind_buffers[i];
                                         if(cstrClientCharset) {                                          if( size_t value_length=strlen(bind_buffer) ) {
                                                 if(ph.value) {                                                  char* returned_value=(char*)services.malloc_atomic(value_length+1/*terminator*/);
                                                         size_t value_length;                                                  memcpy(returned_value, bind_buffer, value_length+1 );
                                                         services.transcode(ph.value, strlen(ph.value),                                                  ph.value=returned_value;
                                                                 ph.value, value_length,  
                                                   if(cstrClientCharset) {
                                                           services.transcode(ph.value, value_length,
                                                                   ph.value, value_length/*<this new value is not used afterwards, actually*/,
                                                                 cstrClientCharset,                                                                  cstrClientCharset,
                                                                 services.request_charset());                                                                  services.request_charset());
                                                 }                                                  }
                                           } else {
                                                   ph.value=0;
                                         }                                          }
                                 }                                  }
                         }                          }
Line 682  private: // private funcs Line 722  private: // private funcs
                         (ub4 *)0, OCI_ATTR_STMT_TYPE, connection.errhp));                          (ub4 *)0, OCI_ATTR_STMT_TYPE, connection.errhp));
         */          */
   
                 while(isspace(*statement))                   while(isspace((unsigned char)*statement)) 
                         statement++;                          statement++;
                 if(strncasecmp(statement, "select", 6)==0)                   if(strncasecmp(statement, "select", 6)==0) 
                         stmt_type=OCI_STMT_SELECT;                          stmt_type=OCI_STMT_SELECT;

Removed from v.1.60  
changed lines
  Added in v.1.67


E-mail: