Diff for /sql/pgsql/parser3pgsql.C between versions 1.41 and 1.47

version 1.41, 2012/06/15 09:09:33 version 1.47, 2021/11/03 14:51:51
Line 1 Line 1
 /** @file  /** @file
         Parser PgSQL driver.          Parser PgSQL driver.
   
         Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2019 Art. Lebedev Studio (http://www.artlebedev.com)
   
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
   
Line 99  struct Connection { Line 99  struct Connection {
         PGconn *conn;          PGconn *conn;
         const char* client_charset;          const char* client_charset;
         bool autocommit;          bool autocommit;
         bool without_default_transactions;          bool standard_conforming_strings;
 };  };
   
 /**  /**
Line 133  public: Line 133  public:
                         ClientCharset=charset&  // transcode by parser                          ClientCharset=charset&  // transcode by parser
                         charset=value&                  // transcode by server with 'SET CLIENT_ENCODING=value'                          charset=value&                  // transcode by server with 'SET CLIENT_ENCODING=value'
                         datestyle=value&                // 'SET DATESTYLE=value' available values are: ISO|SQL|Postgres|European|US|German [default=ISO]                          datestyle=value&                // 'SET DATESTYLE=value' available values are: ISO|SQL|Postgres|European|US|German [default=ISO]
                         autocommit=1&                   // each transaction is commited automatically (default)                          autocommit=0&                   // 1 -- each statement is commited automatically, only when with_default_transaction enabled
                         WithoutDefaultTransaction=0     // 1 -- disable any BEGIN TRAN/COMMIT/ROLLBACK [can NOT be used with autocommit option]                          standard_conforming_strings=1&  // 0 -- escape \ char that could be needed for old servers
         */          */
         void connect(          void connect(
                                 char* url,                                   char* url, 
Line 153  public: Line 153  public:
                 char* datestyle=0;                  char* datestyle=0;
   
                 Connection& connection=*(Connection *)services.malloc(sizeof(Connection));                  Connection& connection=*(Connection *)services.malloc(sizeof(Connection));
   
                 *connection_ref=&connection;                  *connection_ref=&connection;
                 connection.services=&services;                  connection.services=&services;
                 connection.client_charset=0;                      connection.client_charset=0;
                 connection.autocommit=true;                  connection.autocommit=true;
                 connection.without_default_transactions=false;                  connection.standard_conforming_strings=true;
   
                 connection.conn=PQsetdbLogin(                  connection.conn=PQsetdbLogin(
                         (host&&strcasecmp(host, "local")==0)?NULL/* local Unix domain socket */:host, port,                           (host&&strcasecmp(host, "local")==0)?NULL/* local Unix domain socket */:host, port, 
Line 181  public: Line 182  public:
                                                 } else if(strcasecmp(key, "datestyle")==0){                                                  } else if(strcasecmp(key, "datestyle")==0){
                                                         datestyle=value;                                                          datestyle=value;
                                                 } else if(strcasecmp(key, "autocommit")==0){                                                  } else if(strcasecmp(key, "autocommit")==0){
                                                         if(connection.without_default_transactions)  
                                                                 services._throw("options WithoutDefaultTransaction and autocommit can't be used together");  
                                                         if(atoi(value)==0)                                                          if(atoi(value)==0)
                                                                 connection.autocommit=false;                                                                  connection.autocommit=false;
                                                 } else if(strcmp(key, "WithoutDefaultTransaction")==0){                                                  } else if(strcasecmp(key, "standard_conforming_strings")==0){
                                                         if(!connection.autocommit)                                                          if(atoi(value)==0)
                                                                 services._throw("options WithoutDefaultTransaction and autocommit can't be used together");                                                                  connection.standard_conforming_strings=false;
                                                         if(atoi(value)==1){  
                                                                 connection.without_default_transactions=true;  
                                                                 connection.autocommit=false;  
                                                         }  
                                                 } else                                                  } else
                                                         services._throw("unknown connect option" /*key*/);                                                          services._throw("unknown connect option" /*key*/);
                                         } else                                           } else 
Line 214  public: Line 209  public:
                         _execute_cmd(connection, statement);                          _execute_cmd(connection, statement);
                 }                  }
   
                 _transaction_begin(connection);                  if(!connection.autocommit)
                           _execute_cmd(connection, "set AUTOCOMMIT off");
         }          }
   
         void disconnect(void *aconnection){          void disconnect(void *aconnection){
Line 225  public: Line 221  public:
   
         void commit(void *aconnection){          void commit(void *aconnection){
                 Connection& connection=*static_cast<Connection*>(aconnection);                  Connection& connection=*static_cast<Connection*>(aconnection);
                 _transaction_commit(connection);                  if(!connection.autocommit)
                 _transaction_begin(connection);                          _execute_cmd(connection, "COMMIT");
         }          }
   
         void rollback(void *aconnection){          void rollback(void *aconnection){
                 Connection& connection=*static_cast<Connection*>(aconnection);                  Connection& connection=*static_cast<Connection*>(aconnection);
                 _transaction_rollback(connection);                  if(!connection.autocommit)
                 _transaction_begin(connection);                          _execute_cmd(connection, "ROLLBACK");
         }          }
   
         bool ping(void *aconnection) {          bool ping(void *aconnection) {
Line 244  public: Line 240  public:
         // thus we can't use the sql server quoting support          // thus we can't use the sql server quoting support
         const char* quote(void *aconnection, const char *str, unsigned int length)           const char* quote(void *aconnection, const char *str, unsigned int length) 
         {          {
                   Connection& connection=*static_cast<Connection*>(aconnection);
   
                 const char* from;                  const char* from;
                 const char* from_end=str+length;                  const char* from_end=str+length;
   
                 size_t quoted=0;                  size_t quoted=0;
   
                 for(from=str; from<from_end; from++){                  if(connection.standard_conforming_strings){
                         switch (*from) {                          for(from=str; from<from_end; from++){
                         case '\'':                                  if(*from=='\'')
                         case '\\':                                          quoted++;
                                 quoted++;                          }
                   } else {
                           for(from=str; from<from_end; from++){
                                   switch (*from) {
                                   case '\'':
                                   case '\\':
                                           quoted++;
                                   }
                         }                          }
                 }                  }
   
                 if(!quoted)                  if(!quoted)
                         return str;                          return str;
   
                 Connection& connection=*static_cast<Connection*>(aconnection);  
                 char *result=(char*)connection.services->malloc_atomic(length + quoted + 1);                  char *result=(char*)connection.services->malloc_atomic(length + quoted + 1);
                 char *to = result;                  char *to = result;
   
                 for(from=str; from<from_end; from++){                  if(connection.standard_conforming_strings){
                         switch (*from) {                          for(from=str; from<from_end; from++){
                         case '\'': // "'" -> "''"                                  if(*from=='\'')
                                 *to++='\'';                                          *to++= '\''; // "'" -> "''"
                                 break;                                  *to++=*from;
                         case '\\': // "\" -> "\\"                          }
                                 *to++='\\';                  } else {
                                 break;                          for(from=str; from<from_end; from++){
                                   switch (*from) {
                                   case '\'': // "'" -> "''"
                                           *to++= '\'';
                                           break;
                                   case '\\': // "\" -> "\\"
                                           *to++='\\';
                                           break;
                                   }
                                   *to++=*from;
                         }                          }
                         *to++=*from;  
                 }                  }
                                   
                 *to=0;                  *to=0;
Line 332  public: Line 344  public:
                                 break;                                  break;
                         case PGRES_COMMAND_OK: // empty result: insert|delete|update|...                          case PGRES_COMMAND_OK: // empty result: insert|delete|update|...
                                 PQclear(res);                                  PQclear(res);
                                 if(connection.autocommit)  
                                         commit(aconnection);  
                                 return;                                  return;
                         case PGRES_TUPLES_OK:                           case PGRES_TUPLES_OK: 
                                 break;                                    break;
                         default:                          default:
                                 PQclear_throwPQerror;                                  PQclear_throwPQerror;
                                 break;                                  break;
Line 460  cleanup: Line 470  cleanup:
                 PQclear(res);                  PQclear(res);
                 if(failed)                  if(failed)
                         services._throw(sql_error);                          services._throw(sql_error);
   
                 if(connection.autocommit)  
                         commit(aconnection);  
         }          }
   
 private:  private:
Line 498  private: Line 505  private:
                 }                  }
         }          }
                   
           
         void _transaction_begin(Connection& connection){  
                 _execute_transactions_cmd(connection, "BEGIN");  
         }  
   
         void _transaction_commit(Connection& connection){  
                 _execute_transactions_cmd(connection, "COMMIT");  
         }  
   
         void _transaction_rollback(Connection& connection){  
                 _execute_transactions_cmd(connection, "ROLLBACK");  
         }  
   
         void _execute_transactions_cmd(const Connection& connection, const char *query){  
                 if(!connection.without_default_transactions) // with option ?WithoutDefaultTransaction=1 user must execute BEGIN/COMMIT/ROLLBACK by himself  
                         _execute_cmd(connection, query);  
         }  
   
         // executes a query and throw away the result.          // executes a query and throw away the result.
         void _execute_cmd(const Connection& connection, const char *query){          void _execute_cmd(const Connection& connection, const char *query){
                 if(PGresult *res=PQexec(connection.conn, query))                  if(PGresult *res=PQexec(connection.conn, query))

Removed from v.1.41  
changed lines
  Added in v.1.47


E-mail: