File indexing completed on 2025-02-23 05:15:20

0001 //
0002 // Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #define SOCI_POSTGRESQL_SOURCE
0009 #include "soci/postgresql/soci-postgresql.h"
0010 #include "soci/connection-parameters.h"
0011 #include "soci/backend-loader.h"
0012 #include <libpq/libpq-fs.h> // libpq
0013 
0014 #ifdef _MSC_VER
0015 #pragma warning(disable:4355)
0016 #endif
0017 
0018 using namespace soci;
0019 using namespace soci::details;
0020 
0021 namespace // unnamed
0022 {
0023 
0024 // iterates the string pointed by i, searching for pairs of key value.
0025 // it returns the position after the value
0026 std::string::const_iterator get_key_value(std::string::const_iterator & i,
0027                                           std::string::const_iterator const & end,
0028                                           std::string & key,
0029                                           std::string & value)
0030 {
0031     bool in_value = false;
0032     bool quoted = false;
0033 
0034     key.clear();
0035     value.clear();
0036 
0037     while (i != end)
0038     {
0039         if (in_value == false)
0040         {
0041             if (*i == '=')
0042             {
0043                 in_value = true;
0044                 if (i != end && *(i + 1) == '"')
0045                 {
0046                     quoted = true;
0047                     ++i; // jump over the quote
0048                 }
0049             }
0050             else if (!isspace(*i))
0051             {
0052                 key += *i;
0053             }
0054         }
0055         else
0056         {
0057             if ((quoted == true && *i == '"') || (quoted == false && isspace(*i)))
0058             {
0059                 return ++i;
0060             }
0061             else
0062             {
0063                 value += *i;
0064             }
0065         }
0066         ++i;
0067     }
0068     return i;
0069 }
0070 
0071 // retrieves specific parameters from the
0072 // uniform connect string
0073 std::string chop_connect_string(std::string const & connectString,
0074     bool & single_row_mode)
0075 {
0076     std::string pruned_conn_string;
0077 
0078     single_row_mode = false;
0079 
0080     std::string key, value;
0081     std::string::const_iterator i = connectString.begin();
0082     while (i != connectString.end())
0083     {
0084         i = get_key_value(i, connectString.end(), key, value);
0085         if (key == "singlerow" || key == "singlerows")
0086         {
0087             single_row_mode = (value == "true" || value == "yes");
0088         }
0089         else
0090         {
0091             if (pruned_conn_string.empty() == false)
0092             {
0093                 pruned_conn_string += ' ';
0094             }
0095 
0096             pruned_conn_string += key + '=' + value;
0097         }
0098     }
0099 
0100     return pruned_conn_string;
0101 }
0102 
0103 } // unnamed namespace
0104 
0105 // concrete factory for Empty concrete strategies
0106 postgresql_session_backend * postgresql_backend_factory::make_session(
0107      connection_parameters const & parameters) const
0108 {
0109     bool single_row_mode;
0110 
0111     const std::string pruned_conn_string =
0112         chop_connect_string(parameters.get_connect_string(), single_row_mode);
0113 
0114     connection_parameters pruned_parameters(parameters);
0115     pruned_parameters.set_connect_string(pruned_conn_string);
0116 
0117     return new postgresql_session_backend(pruned_parameters, single_row_mode);
0118 }
0119 
0120 postgresql_backend_factory const soci::postgresql;
0121 
0122 extern "C"
0123 {
0124 
0125 // for dynamic backend loading
0126 SOCI_POSTGRESQL_DECL backend_factory const * factory_postgresql()
0127 {
0128     return &soci::postgresql;
0129 }
0130 
0131 SOCI_POSTGRESQL_DECL void register_factory_postgresql()
0132 {
0133     soci::dynamic_backends::register_backend("postgresql", soci::postgresql);
0134 }
0135 
0136 } // extern "C"