Diff for /sql/odbc/parser3odbc.C between versions 1.13.6.2 and 1.23

version 1.13.6.2, 2003/07/22 11:23:09 version 1.23, 2004/06/23 07:32:07
Line 18  static const char *RCSId="$Id$"; Line 18  static const char *RCSId="$Id$";
   
 #include "pa_sql_driver.h"  #include "pa_sql_driver.h"
   
   #define WINVER 0x0400
 #include <AFXDB.H>  #include <AFXDB.H>
   
 // defines  // defines
Line 55  static char *lsplit(char *string, char d Line 56  static char *lsplit(char *string, char d
     return 0;      return 0;
 }  }
   
   static void toupper_str(char *out, const char *in, size_t size) {
           while(size--)
                   *out++=(char)toupper(*in++);
   }
   
   struct Connection {
           SQL_Driver_services* services;
   
           CDatabase* db;
           const char* cstrClientCharset;
   };
   
 /**  /**
         ODBC server driver          ODBC server driver
 */  */
Line 68  public: Line 81  public:
         int api_version() { return SQL_DRIVER_API_VERSION; }          int api_version() { return SQL_DRIVER_API_VERSION; }
         const char *initialize(char *dlopen_file_spec) { return 0; }          const char *initialize(char *dlopen_file_spec) { return 0; }
         /**     connect          /**     connect
                 @param used_only_in_connect_url                  @param url
                         format: @b DSN=dsn;UID=user;PWD=password (ODBC connect string)                          format: @b DSN=dsn;UID=user;PWD=password (ODBC connect string)
                         WARNING: must be used only to connect, for buffer doesn't live long                          WARNING: must be used only to connect, for buffer doesn't live long
         */          */
         void connect(          void connect(
                 char *used_only_in_connect_url,                   char *url, 
                 SQL_Driver_services& services,                   SQL_Driver_services& services, 
                 void **connection ///< output: CDatabase *                  void **connection_ref ///< output: Connection*
                 ) {                  ) {
         //      _asm int 3;                  Connection& connection=*(Connection  *)services.malloc(sizeof(Connection));
                 CDatabase *db;                  *connection_ref=&connection;
                   connection.services=&services;
                   connection.cstrClientCharset=0;
   
                   if(const char* key_start=strstr(url, "ClientCharset=")) {
                           const char* value_start=key_start+14/*strlen("ClientCharset=")*/;
                           const char* value_end=strchr(value_start, ';');
                           if(!value_end)
                                   value_end=url+strlen(url);
   
                           if(size_t ClientCharsetLength=value_end-value_start) {
                                   char* cstrClientCharset=(char*)services.malloc_atomic(ClientCharsetLength+1);
                                   toupper_str(cstrClientCharset, value_start, ClientCharsetLength);
                                   cstrClientCharset[ClientCharsetLength]=0;
   
                                   connection.cstrClientCharset=cstrClientCharset;
                           }
                   }
   
                 TRY {                  TRY {
                         db=new CDatabase();                          connection.db=new CDatabase();
                         db->OpenEx(used_only_in_connect_url, CDatabase::noOdbcDialog);                          connection.db->OpenEx(url, CDatabase::noOdbcDialog);
                         db->BeginTrans();                          connection.db->BeginTrans();
                 }                   } 
                 CATCH_ALL (e) {                  CATCH_ALL (e) {
                         _throw(services, e);                          _throw(services, e);
                         db=0; // calm, compiler  
                 }                  }
                 END_CATCH_ALL                  END_CATCH_ALL
   
                 *(CDatabase **)connection=db;  
         }          }
         void disconnect(void *connection) {          void disconnect(void *aconnection) {
                 CDatabase *db=static_cast<CDatabase *>(connection);                  Connection& connection=*static_cast<Connection*>(aconnection);
                 TRY                  TRY
                         delete db;                          delete connection.db;
                           connection.db=0;
                 CATCH_ALL (e) {                  CATCH_ALL (e) {
                         // nothing                          // nothing
                 }                  }
                 END_CATCH_ALL                  END_CATCH_ALL
         }          }
         void commit(SQL_Driver_services& services, void *connection) {          void commit(void *aconnection) {
                 CDatabase *db=static_cast<CDatabase *>(connection);                  Connection& connection=*static_cast<Connection*>(aconnection);
                 TRY                  TRY
                         db->CommitTrans();                          connection.db->CommitTrans();
                         db->BeginTrans();                          connection.db->BeginTrans();
                 CATCH_ALL (e) {                  CATCH_ALL (e) {
                         _throw(services, e);                          _throw(*connection.services, e);
                 }                  }
                 END_CATCH_ALL                  END_CATCH_ALL
         }          }
         void rollback(SQL_Driver_services& services, void *connection) {          void rollback(void *aconnection) {
                 CDatabase *db=static_cast<CDatabase *>(connection);                  Connection& connection=*static_cast<Connection*>(aconnection);
                 TRY                  TRY
                         db->Rollback();                          connection.db->Rollback();
                         db->BeginTrans();                          connection.db->BeginTrans();
                 CATCH_ALL (e) {                  CATCH_ALL (e) {
                         _throw(services, e);                          _throw(*connection.services, e);
                 }                  }
                 END_CATCH_ALL                  END_CATCH_ALL
         }          }
   
         bool ping(SQL_Driver_services&, void *connection) {          bool ping(void *connection) {
                 return true;                  return true;
         }          }
   
         const char* quote(          const char* quote(void *aconnection, const char *from, unsigned int length) {
                 SQL_Driver_services& services, void *connection,                  Connection& connection=*static_cast<Connection*>(aconnection);
                 const char *from, unsigned int length) {                  char *result=(char*)connection.services->malloc_atomic(length*2+1);
                 char *result=(char*)services.malloc_atomic(length*2+1);  
                 char *to=result;                  char *to=result;
                 while(length--) {                  while(length--) {
                         if(*from=='\'') { // ' -> ''                          if(*from=='\'') { // ' -> ''
                                 *to++='\''; result++;                                  *to++='\'';
                         }                          }
                         *to++=*from++;                          *to++=*from++;
                 }                  }
                 *to=0;                  *to=0;
                 return result;                  return result;
         }          }
         void query(          void query(void *aconnection, 
                 SQL_Driver_services& services, void *connection,                   const char *statement, 
                 const char *statement, unsigned long offset, unsigned long limit,                  size_t placeholders_count, Placeholder* placeholders, 
                   unsigned long offset, unsigned long limit,
                 SQL_Driver_query_event_handlers& handlers) {                  SQL_Driver_query_event_handlers& handlers) {
   
                 CDatabase *db=static_cast<CDatabase *>(connection);                  Connection& connection=*static_cast<Connection*>(aconnection);
                   CDatabase *db=connection.db;
                   SQL_Driver_services& services=*connection.services;
   
                   if(placeholders_count>0)
                           services._throw("bind variables not supported (yet)");
   
                   // transcode from $request:charset to connect-string?client_charset
                   if(const char* cstrClientCharset=connection.cstrClientCharset) {
                           size_t transcoded_statement_size;
                           services.transcode(statement, strlen(statement),
                                   statement, transcoded_statement_size,
                                   services.request_charset(),
                                   cstrClientCharset);
                   }
   
                 while(isspace(*statement))                   while(isspace(*statement)) 
                         statement++;                          statement++;
Line 199  public: Line 242  public:
                                         CODBCFieldInfo fieldinfo;                                          CODBCFieldInfo fieldinfo;
                                         rs.GetODBCFieldInfo(i, fieldinfo);                                          rs.GetODBCFieldInfo(i, fieldinfo);
                                         column_types[i]=fieldinfo.m_nSQLType;                                          column_types[i]=fieldinfo.m_nSQLType;
                                         size_t size=fieldinfo.m_strName.GetLength();                                          size_t length=fieldinfo.m_strName.GetLength();
                                         char *str=0;                                          char *str=0;
                                         if(size) {                                          if(length) {
                                                 str=(char*)services.malloc_atomic(size+1);                                                  str=(char*)services.malloc_atomic(length+1);
                                                 memcpy(str, (char *)LPCTSTR(fieldinfo.m_strName), size+1);                                                  memcpy(str, (char *)LPCTSTR(fieldinfo.m_strName), length+1);
   
                                                   // transcode to $request:charset from connect-string?client_charset
                                                   if(const char* cstrClientCharset=connection.cstrClientCharset) {
                                                           services.transcode(str, length,
                                                                   str, length,
                                                                   cstrClientCharset,
                                                                   services.request_charset());
                                                   }
                                         }                                          }
                                         CHECK(handlers.add_column(sql_error, str, size));                                          CHECK(handlers.add_column(sql_error, str, length));
                                 }                                  }
   
                                 CHECK(handlers.before_rows(sql_error));                                  CHECK(handlers.before_rows(sql_error));
Line 217  public: Line 268  public:
                                         if(row>=offset) {                                          if(row>=offset) {
                                                 CHECK(handlers.add_row(sql_error));                                                  CHECK(handlers.add_row(sql_error));
                                                 for(int i=0; i<column_count; i++) {                                                  for(int i=0; i<column_count; i++) {
                                                         size_t size;                                                          size_t length;
                                                         char* str;                                                          char* str;
                                                         switch(column_types[i]) {                                                          switch(column_types[i]) {
                                                         //case xBOOL:                                                          //case xBOOL:
Line 227  public: Line 278  public:
                                                         case SQL_VARBINARY:                                                          case SQL_VARBINARY:
                                                         case SQL_LONGVARBINARY:                                                          case SQL_LONGVARBINARY:
                                                         case SQL_SMALLDATETIME:                                                          case SQL_SMALLDATETIME:
                                                           //case SQL_NVARCHAR: // mfc 7.1 has errors with nvarchar(length): SQLGetData in dbcore.cpp truncates last byte for unknown reason.  could be fixed by uncommenting this and handing DBVT_WSTRING inside, but it's UNICODE
                                                                 rs.GetFieldValue(i, v);                                                                  rs.GetFieldValue(i, v);
                                                                 getFromDBVariant(services, v, str, size);                                                                  getFromDBVariant(services, v, str, length);
                                                                 break;                                                                  break;
                                                         default:                                                          default:
                                                                 rs.GetFieldValue(i, s);                                                                  rs.GetFieldValue(i, s);
                                                                 getFromString(services, s, str, size);                                                                  getFromString(services, s, str, length);
                                                                 break;                                                                  break;
                                                         }                                                          }
                                                         CHECK(handlers.add_row_cell(sql_error, str, size));  
                                                           // transcode to $request:charset from connect-string?client_charset
                                                           if(const char* cstrClientCharset=connection.cstrClientCharset)
                                                                   services.transcode(str, length,
                                                                           str, length,
                                                                           cstrClientCharset,
                                                                           services.request_charset());
   
                                                           CHECK(handlers.add_row_cell(sql_error, str, length));
                                                 }                                                  }
                                         }                                          }
                                         rs.MoveNext();  row++;                                          rs.MoveNext();  row++;
Line 250  public: Line 310  public:
                 } END_CATCH_ALL                  } END_CATCH_ALL
         }          }
   
         void getFromDBVariant(SQL_Driver_services& services, CDBVariant& v, char*& str, size_t& size) {          void getFromDBVariant(SQL_Driver_services& services, CDBVariant& v, char*& str, size_t& length) {
                 switch(v.m_dwType) {                  switch(v.m_dwType) {
                 case DBVT_BINARY: /* << would cause problems with current String implementation                  case DBVT_BINARY: /* << would cause problems with current String implementation
                                   now falling into NULL case, effectively ignoring such columns [not failing]                                    now falling into NULL case, effectively ignoring such columns [not failing]
                         {                          {
                                 if(size=v.m_pbinary->m_dwDataLength) {                                  if(length=v.m_pbinary->m_dwDataLength) {
                                         str=services.malloc_atomic(size+1);                                          str=services.malloc_atomic(length+1);
                                         memcpy(ptr, ::GlobalLock(v.m_pbinary->m_hData), size);                                          memcpy(ptr, ::GlobalLock(v.m_pbinary->m_hData), length);
                                         ::GlobalUnlock(v.m_pbinary->m_hData);                                          ::GlobalUnlock(v.m_pbinary->m_hData);
                                 } else                                   } else 
                                         str=0;                                          str=0;
Line 265  public: Line 325  public:
                         }*/                           }*/ 
                 case DBVT_NULL: // No union member is valid for access.                   case DBVT_NULL: // No union member is valid for access. 
                         str=0;                          str=0;
                         size=0;                          length=0;
                         break;                          break;
 /*              case DBVT_BOOL:  /*              case DBVT_BOOL:
                         ptr=v.m_boolVal?"1":"0";                          ptr=v.m_boolVal?"1":"0";
                         size=1;                          length=1;
                         break;*/                          break;*/
 /*                                                      case DBVT_UCHAR:  /*                                                      case DBVT_UCHAR:
                         size=strlen(ptr=v.m_chVal);                          length=strlen(ptr=v.m_chVal);
                         break;                          break;
                 case DBVT_SHORT:                  case DBVT_SHORT:
                         char buf[MAX_NUMBER];                          char buf[MAX_NUMBER];
                         size=snprintf(HEAPIZE buf, "%d", v.m_iVal);                          length=snprintf(HEAPIZE buf, "%d", v.m_iVal);
                         break;*/                          break;*/
 /*              case DBVT_LONG:   /*              case DBVT_LONG: 
                         {                          {
                                 char local_buf[MAX_NUMBER];                                  char local_buf[MAX_NUMBER];
                                 size=snprintf(local_buf, MAX_NUMBER, "%ld", v.m_lVal);                                  length=snprintf(local_buf, MAX_NUMBER, "%ld", v.m_lVal);
                                 ptr=services.malloc_atomic(size);                                  ptr=services.malloc_atomic(length);
                                 memcpy(ptr, local_buf, size);                                  memcpy(ptr, local_buf, length);
                                 break;                                  break;
                         }*/                          }*/
                 /*case DBVT_SINGLE:                  /*case DBVT_SINGLE:
                         m_fltVal                           m_fltVal 
                         break;                          break;
         case DBVT_DOUBLE m_dblVal           case DBVT_DOUBLE m_dblVal 
         case DBVT_STRING m_pstring */          case DBVT_STRING m_pstring */ 
                 case DBVT_DATE:                  case DBVT_DATE:
                         {                          {
                                 char local_buf[MAX_STRING];                                  char local_buf[MAX_STRING];
                                 size=snprintf(local_buf, MAX_STRING,                                   length=snprintf(local_buf, MAX_STRING, 
                                         "%04d-%02d-%02d %02d:%02d:%02d.%03d",                                          "%04d-%02d-%02d %02d:%02d:%02d.%03d",
                                         v.m_pdate->year,                                           v.m_pdate->year, 
                                         v.m_pdate->month,                                          v.m_pdate->month,
Line 303  public: Line 363  public:
                                         v.m_pdate->minute,                                          v.m_pdate->minute,
                                         v.m_pdate->second,                                          v.m_pdate->second,
                                         v.m_pdate->fraction);                                          v.m_pdate->fraction);
                                 str=(char*)services.malloc_atomic(size+1);                                  str=(char*)services.malloc_atomic(length+1);
                                 memcpy(str, local_buf, size+1);                                  memcpy(str, local_buf, length+1);
                                 break;                                  break;
                         }                          }
                 default:                  default:
Line 315  public: Line 375  public:
                 }                  }
         }          }
   
         void getFromString(SQL_Driver_services& services, CString& s, char*& astr, size_t& size) {          void getFromString(SQL_Driver_services& services, CString& s, char*& astr, size_t& length) {
                 if(s.IsEmpty()) {                  if(s.IsEmpty()) {
                         astr=0;                          astr=0;
                         size=0;                          length=0;
                 } else {                  } else {
                         const char *cstr=LPCTSTR(s);                          const char *cstr=LPCTSTR(s);
                         size=strlen(cstr); //string.GetLength() works wrong with non-string types:                           length=strlen(cstr); //string.GetLength() works wrong with non-string types: 
                         astr=(char*)services.malloc_atomic(size+1);                          astr=(char*)services.malloc_atomic(length+1);
                         memcpy(astr, cstr, size+1);                          memcpy(astr, cstr, length+1);
                 }                  }
         }          }
   

Removed from v.1.13.6.2  
changed lines
  Added in v.1.23


E-mail: