Diff for /sql/pgsql/parser3pgsql.C between versions 1.18 and 1.26

version 1.18, 2004/03/05 10:16:41 version 1.26, 2007/01/26 10:10:32
Line 22  static const char *RCSId="$Id$"; Line 22  static const char *RCSId="$Id$";
 // actually writing chunks of that size failed, reduced it twice  // actually writing chunks of that size failed, reduced it twice
 #define LO_BUFSIZE                0x1000  #define LO_BUFSIZE                0x1000
 // from postgres_ext.h  // from postgres_ext.h
 #define InvalidOid              ((Oid) 0)  //#define InvalidOid            ((Oid) 0)
   
   
 #include "ltdl.h"  #include "ltdl.h"
Line 58  static char *lsplit(char **string_ref, c Line 58  static char *lsplit(char **string_ref, c
     return result;      return result;
 }  }
   
 static void toupper(char *out, const char *in, size_t size) {  static char* rsplit(char* string, char delim) {
       if(string) {
                   char* v=strrchr(string, delim); 
                   if(v) {
                           *v=0;
                           return v+1;
                   }
       }
       return NULL;        
   }
   
   static void toupper_str(char *out, const char *in, size_t size) {
         while(size--)          while(size--)
                 *out++=(char)toupper(*in++);                  *out++=(char)toupper(*in++);
 }  }
Line 95  public: Line 106  public:
         #define PQclear_throwPQerror PQclear_throw(PQerrorMessage(connection.conn))          #define PQclear_throwPQerror PQclear_throw(PQerrorMessage(connection.conn))
   
         /**     connect          /**     connect
                 @param used_only_in_connect_url                  @param url
                         format: @b user:pass@host[:port]|[local]/database                          format: @b user:pass@host[:port]|[local]/database
         */          */
         void connect(          void connect(
                 char *used_only_in_connect_url,                   char *url, 
                 SQL_Driver_services& services,                   SQL_Driver_services& services, 
                 void **connection_ref ///< output: Connection*                  void **connection_ref ///< output: Connection*
                 ) {                  ) {
                 char *user=used_only_in_connect_url;                  char *user=url;
                 char *host=lsplit(user, '@');                  char *host=rsplit(user, '@');
                 char *db=lsplit(host, '/');                  char *db=lsplit(host, '/');
                 char *pwd=lsplit(user, ':');                  char *pwd=lsplit(user, ':');
                 char *port=lsplit(host, ':');                  char *port=lsplit(host, ':');
Line 127  public: Line 138  public:
   
                 char *charset=0;                  char *charset=0;
                 char *datestyle=0;                  char *datestyle=0;
                   isDefaultTransaction = true;
   
                 while(options) {                  while(options) {
                         if(char *key=lsplit(&options, '&')) {                          if(char *key=lsplit(&options, '&')) {
                                 if(*key) {                                  if(*key) {
                                         if(char *value=lsplit(key, '=')) {                                          if(char *value=lsplit(key, '=')) {
                                                 if(strcmp(key, "ClientCharset" ) == 0) {                                                  if(strcmp(key, "ClientCharset" ) == 0) {
                                                         toupper(value, value, strlen(value));                                                          toupper_str(value, value, strlen(value));
                                                         connection.cstrClientCharset=value;                                                          connection.cstrClientCharset=value;
                                                 } else if(strcasecmp(key, "charset")==0) { // left for backward compatibility, consider using ClientCharset                                                  } else if(strcasecmp(key, "charset")==0) { // left for backward compatibility, consider using ClientCharset
                                                         cstrBackwardCompAskServerToTranscode=value;                                                          cstrBackwardCompAskServerToTranscode=value;
                                                 } else if(strcasecmp(key, "datestyle")==0) {                                                  } else if(strcasecmp(key, "datestyle")==0) {
                                                         datestyle=value;                                                          datestyle=value;
                                                   } else if(strcmp(key, "WithoutDefaultTransaction")==0) {
                                                           if(strcmp(value, "1" ) == 0) {
                                                                   isDefaultTransaction = false;
                                                           } else if(strcmp(value, "0" ) == 0) {
                                                                   isDefaultTransaction = true;
                                                           } else {
                                                                   services._throw("Bad WithoutDefaultTransaction option value. Only 0 or 1 are accepted." /*value*/);
                                                           }
                                                 } else                                                  } else
                                                         services._throw("unknown connect option" /*key*/);                                                          services._throw("unknown connect option" /*key*/);
                                         } else                                           } else 
Line 155  public: Line 175  public:
                         // set CLIENT_ENCODING                          // set CLIENT_ENCODING
                         char statement[MAX_STRING]="set CLIENT_ENCODING="; // win                          char statement[MAX_STRING]="set CLIENT_ENCODING="; // win
                         strncat(statement, cstrBackwardCompAskServerToTranscode, MAX_STRING);                          strncat(statement, cstrBackwardCompAskServerToTranscode, MAX_STRING);
                           
                         PGresult *res=PQexec(connection.conn, statement);                          execute_resultless(connection, statement);
                         if(!res)   
                                 throwPQerror;  
                         PQclear(res); // throw out the result [don't need but must call]  
                 }                  }
   
                 if(datestyle) {                  if(datestyle) {
                         // set DATESTYLE                          // set DATESTYLE
                         char statement[MAX_STRING]="set DATESTYLE="; // ISO,SQL,Postgres,European,NonEuropean=US,German,DEFAULT=ISO                          char statement[MAX_STRING]="set DATESTYLE="; // ISO,SQL,Postgres,European,NonEuropean=US,German,DEFAULT=ISO
                         strncat(statement, charset, MAX_STRING);                          strncat(statement, charset, MAX_STRING);
                           
                         PGresult *res=PQexec(connection.conn, statement);                          execute_resultless(connection, statement);
                         if(!res)   
                                 throwPQerror;  
                         PQclear(res); // throw out the result [don't need but must call]  
                 }                  }
   
                 begin_transaction(connection);                  begin_transaction(connection);
Line 182  public: Line 196  public:
                 connection.conn=0;                  connection.conn=0;
         }          }
         void commit(void *aconnection) {          void commit(void *aconnection) {
                 Connection& connection=*static_cast<Connection*>(aconnection);                  execute_transaction_cmd(aconnection, "COMMIT");
   
                 if(PGresult *res=PQexec(connection.conn, "COMMIT"))  
                         PQclear(res);  
                 else  
                         throwPQerror;  
                 begin_transaction(connection);  
         }          }
         void rollback(void *aconnection) {          void rollback(void *aconnection) {
                 Connection& connection=*static_cast<Connection*>(aconnection);                  execute_transaction_cmd(aconnection, "ROLLBACK");
   
                 if(PGresult *res=PQexec(connection.conn, "ROLLBACK"))  
                         PQclear(res);  
                 else  
                         throwPQerror;  
                 begin_transaction(connection);  
         }          }
   
         bool ping(void *aconnection) {          bool ping(void *aconnection) {
Line 212  public: Line 214  public:
                 Connection& connection=*static_cast<Connection*>(aconnection);                  Connection& connection=*static_cast<Connection*>(aconnection);
   
                 char *result=(char*)connection.services->malloc_atomic(length*2+1);                  char *result=(char*)connection.services->malloc_atomic(length*2+1);
                 char *to=result;                  int err = 0;
                 while(length--) {                  PQescapeStringConn (connection.conn,
                         switch(*from) {                             result, from, length,
                         case '\'': // "'" -> "''"                             &err);
                                 *to++='\'';  
                                 break;  
                         case '\\': // "\" -> "\\"  
                                 *to++='\\';  
                                 break;  
                         }  
                         *to++=*from++;  
                 }  
                 *to=0;  
                 return result;                  return result;
                 }          }
           
         void query(void *aconnection,           void query(void *aconnection, 
                 const char *astatement, unsigned long offset, unsigned long limit,                  const char *astatement, 
                   size_t placeholders_count, Placeholder* placeholders, 
                   unsigned long offset, unsigned long limit,
                 SQL_Driver_query_event_handlers& handlers) {                  SQL_Driver_query_event_handlers& handlers) {
 //              _asm int 3;  //              _asm int 3;
                 Connection& connection=*static_cast<Connection*>(aconnection);                  Connection& connection=*static_cast<Connection*>(aconnection);
                   const char* cstrClientCharset=connection.cstrClientCharset;
                 SQL_Driver_services& services=*connection.services;                  SQL_Driver_services& services=*connection.services;
                 PGconn *conn=connection.conn;                  PGconn *conn=connection.conn;
   
                   const char** paramValues;
                   if(placeholders_count>0){
                           //services._throw("bind variables not supported (yet)");
                           int binds_size=sizeof(char) * placeholders_count;
                           paramValues = static_cast<const char**>(services.malloc_atomic(binds_size));
                           for(size_t i=0; i<placeholders_count; ++i) {
                                   Placeholder& ph=placeholders[i];
                                   size_t value_length;
                                   if(cstrClientCharset) {
                                           size_t name_length;
                                           services.transcode(ph.name, strlen(ph.name),
                                                   ph.name, name_length,
                                                   services.request_charset(),
                                                   cstrClientCharset);
   
                                           if(ph.value){
                                                   services.transcode(ph.value, strlen(ph.value),
                                                           ph.value, value_length,
                                                           services.request_charset(),
                                                           cstrClientCharset);
                                           }
                                   } else {
                                           value_length=ph.value? strlen(ph.value): 0;
                                   }
                                   if( atoi(ph.name) <= 0 || atoi(ph.name) > placeholders_count) {
                                           services._throw("bad bind parameter key");
                                   }
                                   paramValues[atoi(ph.name)-1] = ph.value;
                           }
                   }
   
                 // transcode from $request:charset to connect-string?client_charset                  // transcode from $request:charset to connect-string?client_charset
                 if(const char* cstrClientCharset=connection.cstrClientCharset) {                  if(cstrClientCharset) {
                         size_t transcoded_statement_size;                          size_t transcoded_statement_size;
                         services.transcode(astatement, strlen(astatement),                          services.transcode(astatement, strlen(astatement),
                                 astatement, transcoded_statement_size,                                  astatement, transcoded_statement_size,
Line 247  public: Line 275  public:
                 const char *statement=preprocess_statement(connection,                  const char *statement=preprocess_statement(connection,
                         astatement, offset, limit);                          astatement, offset, limit);
   
                 PGresult *res=PQexec(conn, statement);                  PGresult *res;
                   if(placeholders_count>0){
                           res=PQexecParams(conn, statement, placeholders_count, NULL, paramValues, NULL, NULL, 0);
                   } else {
                           res=PQexec(conn, statement);
                   }
                 if(!res)                   if(!res) 
                         throwPQerror;                          throwPQerror;
   
Line 281  public: Line 314  public:
                 for(int i=0; i<column_count; i++){                  for(int i=0; i<column_count; i++){
                         char *name=PQfname(res, i);                          char *name=PQfname(res, i);
                         size_t length=strlen(name);                          size_t length=strlen(name);
                         char* str=(char*)services.malloc(length+1);                          char* strm=(char*)services.malloc(length+1);
                         memcpy(str, name, length+1);                          memcpy(strm, name, length+1);
                           const char* str=strm;
   
                         // transcode to $request:charset from connect-string?client_charset                          // transcode to $request:charset from connect-string?client_charset
                         if(const char* cstrClientCharset=connection.cstrClientCharset) {                          if(cstrClientCharset) 
                                 services.transcode(str, length,                                  services.transcode(str, length,
                                         str, length,                                          str, length,
                                         cstrClientCharset,                                          cstrClientCharset,
                                         services.request_charset());                                          services.request_charset());
                         }  
   
                         CHECK(handlers.add_column(sql_error, str, length));                          CHECK(handlers.add_column(sql_error, str, length));
                 }                  }
Line 303  public: Line 336  public:
                                 for(int i=0; i<column_count; i++){                                  for(int i=0; i<column_count; i++){
                                         const char *cell=PQgetvalue(res, r, i);                                          const char *cell=PQgetvalue(res, r, i);
                                         size_t length;                                          size_t length;
                                         char* str;                                          const char* str;
                                         if(PQftype(res, i)==OIDOID) {                                          if(PQftype(res, i)==OIDOID) {
                                                 // ObjectID column, read object bytes                                                  // ObjectID column, read object bytes
   
Line 324  public: Line 357  public:
                                                         length=(size_t)size_tell;                                                          length=(size_t)size_tell;
                                                         if(length) {                                                          if(length) {
                                                                 // read                                                                   // read 
                                                                 str=(char*)services.malloc(length+1);                                                                  char* strm=(char*)services.malloc(length+1);
                                                                 if(!lo_read_ex(conn, fd, str, size_tell))                                                                  if(!lo_read_ex(conn, fd, strm, size_tell))
                                                                         PQclear_throw("lo_read can not read all bytes of object");                                                                          PQclear_throw("lo_read can not read all bytes of object");
                                                                 str[length]=0;                                                                  strm[length]=0;
                                                                   str=strm;
                                                         } else                                                          } else
                                                                 str=0;                                                                  str=0;
                                                         if(lo_close(conn, fd)<0)                                                          if(lo_close(conn, fd)<0)
Line 338  public: Line 372  public:
                                                 // normal column, read it normally                                                  // normal column, read it normally
                                                 length=(size_t)PQgetlength(res, r, i);                                                  length=(size_t)PQgetlength(res, r, i);
                                                 if(length) {                                                  if(length) {
                                                         str=(char*)services.malloc(length+1);                                                          char* strm=(char*)services.malloc(length+1);
                                                         memcpy(str, cell, length+1);                                                          memcpy(strm, cell, length+1);
                                                           str=strm;
                                                 } else                                                  } else
                                                         str=0;                                                          str=0;
                                         }                                          }
   
                                         if(str && length) {                                          if(str && length) {
                                                 // transcode to $request:charset from connect-string?client_charset                                                  // transcode to $request:charset from connect-string?client_charset
                                                 if(const char* cstrClientCharset=connection.cstrClientCharset)                                                  if(cstrClientCharset)
                                                         services.transcode(str, length,                                                          services.transcode(str, length,
                                                                 str, length,                                                                  str, length,
                                                                 cstrClientCharset,                                                                  cstrClientCharset,
Line 364  cleanup: Line 399  cleanup:
   
 private: // private funcs  private: // private funcs
   
         void begin_transaction(Connection& connection) {          void execute_transaction_cmd(void *aconnection, const char *query) {
                 if(PGresult *res=PQexec(connection.conn, "BEGIN"))                  if(isDefaultTransaction)
                         PQclear(res);                  {
                           Connection& connection=*static_cast<Connection*>(aconnection);
                           execute_resultless(connection, query);
                           begin_transaction(connection);
                   }
           }
           
           /**
                   Executes a query and throws the result.
           */
           void execute_resultless(const Connection& connection, const char *query) {
                   if(PGresult *res=PQexec(connection.conn, query))
                           PQclear(res); // throw out the result [don't need but must call]
                 else                  else
                         throwPQerror;                          throwPQerror;
         }          }
   
           void begin_transaction(Connection& connection) {
                   if(isDefaultTransaction)
                   {
                           execute_resultless(connection, "BEGIN");
                   }
           }
   
         const char *preprocess_statement(Connection& connection,          const char *preprocess_statement(Connection& connection,
                 const char *astatement, unsigned long offset, unsigned long limit) {                  const char *astatement, unsigned long offset, unsigned long limit) {
                 PGconn *conn=connection.conn;                  PGconn *conn=connection.conn;
Line 456  private: // private funcs Line 510  private: // private funcs
 private: // lo_read/write exchancements  private: // lo_read/write exchancements
   
         bool lo_read_ex(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len) {          bool lo_read_ex(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len) {
                 int size_read;                  return lo_rw_method (conn, fd, buf, len, lo_read);
                 while(len && (size_read=lo_read(conn, fd, buf, min(LO_BUFSIZE, len)))>0) {  
                         buf+=size_read;  
                         len-=size_read;                                                                   
                 }  
                 return len==0;  
         }          }
   
         bool lo_write_ex(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len) {          bool lo_write_ex(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len) {
                 int size_written;                  return lo_rw_method (conn, fd, buf, len, lo_write);
                 while(len && (size_written=lo_write(conn, fd, buf, min(LO_BUFSIZE, len)))>0) {          }
                         buf+=size_written;  
                         len-=size_written;                                                                                bool lo_rw_method(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len, int (*lo_func)(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len)) {
                   int size_op;
                   while(len && (size_op=lo_func(conn, fd, buf, min(LO_BUFSIZE, len)))>0) {
                           buf+=size_op;
                           len-=size_op;                                                                   
                 }                  }
                 return len==0;                  return len==0;
         }          }
Line 488  private: // conn client library funcs Line 541  private: // conn client library funcs
         typedef ConnStatusType (*t_PQstatus)(const PGconn *conn); t_PQstatus PQstatus;          typedef ConnStatusType (*t_PQstatus)(const PGconn *conn); t_PQstatus PQstatus;
         typedef PGresult *(*t_PQexec)(PGconn *conn,          typedef PGresult *(*t_PQexec)(PGconn *conn,
                          const char *query); t_PQexec PQexec;                           const char *query); t_PQexec PQexec;
   //PQexecParams
           typedef PGresult *(*t_PQexecParams)(
                                              PGconn *conn,
                                              const char *query, 
                                              int nParams,
                          const Oid *paramTypes,
                          const char * const *paramValues,
                          const int *paramLengths,
                          const int *paramFormats,
                          int resultFormat); t_PQexecParams PQexecParams;
   
         typedef ExecStatusType (*t_PQresultStatus)(const PGresult *res); t_PQresultStatus PQresultStatus;          typedef ExecStatusType (*t_PQresultStatus)(const PGresult *res); t_PQresultStatus PQresultStatus;
         typedef int (*t_PQgetlength)(const PGresult *res,          typedef int (*t_PQgetlength)(const PGresult *res,
                                         int tup_num,                                          int tup_num,
Line 503  private: // conn client library funcs Line 567  private: // conn client library funcs
   
         typedef Oid     (*t_PQftype)(const PGresult *res, int field_num); t_PQftype PQftype;          typedef Oid     (*t_PQftype)(const PGresult *res, int field_num); t_PQftype PQftype;
   
           typedef size_t (*t_PQescapeStringConn)(PGconn *conn,
                              char *to, const char *from, size_t length,
                              int *error); t_PQescapeStringConn PQescapeStringConn;
   
         typedef int     (*t_lo_open)(PGconn *conn, Oid lobjId, int mode); t_lo_open lo_open;          typedef int     (*t_lo_open)(PGconn *conn, Oid lobjId, int mode); t_lo_open lo_open;
         typedef int     (*t_lo_close)(PGconn *conn, int fd); t_lo_close lo_close;          typedef int     (*t_lo_close)(PGconn *conn, int fd); t_lo_close lo_close;
         typedef int     (*t_lo_read)(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len); t_lo_read lo_read;          typedef int     (*t_lo_read)(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len); t_lo_read lo_read;
Line 542  private: // conn client library funcs li Line 610  private: // conn client library funcs li
                 DLINK(PQclear);                  DLINK(PQclear);
                 DLINK(PQresultStatus);                  DLINK(PQresultStatus);
                 DLINK(PQexec);                  DLINK(PQexec);
                   DLINK(PQexecParams);
                 DLINK(PQftype);                  DLINK(PQftype);
                   DLINK(PQescapeStringConn);
                 DLINK(lo_open);         DLINK(lo_close);                  DLINK(lo_open);         DLINK(lo_close);
                 DLINK(lo_read);         DLINK(lo_write);                  DLINK(lo_read);         DLINK(lo_write);
                 DLINK(lo_lseek);                DLINK(lo_creat);                  DLINK(lo_lseek);                DLINK(lo_creat);
Line 552  private: // conn client library funcs li Line 622  private: // conn client library funcs li
                 return 0;                  return 0;
         }          }
   
           bool isDefaultTransaction;
 };  };
   
 extern "C" SQL_Driver *SQL_DRIVER_CREATE() {  extern "C" SQL_Driver *SQL_DRIVER_CREATE() {

Removed from v.1.18  
changed lines
  Added in v.1.26


E-mail: