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

0001 //
0002 // Copyright (C) 2004-2007 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_ORACLE_SOURCE
0009 #include "soci/oracle/soci-oracle.h"
0010 #include "soci/connection-parameters.h"
0011 #include "soci/backend-loader.h"
0012 #include <cctype>
0013 #include <cstdio>
0014 #include <cstring>
0015 #include <ctime>
0016 #include <sstream>
0017 
0018 #ifdef _MSC_VER
0019 #pragma warning(disable:4355)
0020 #endif
0021 
0022 using namespace soci;
0023 using namespace soci::details;
0024 
0025 // iterates the string pointed by i, searching for pairs of key value.
0026 // it returns the position after the value
0027 std::string::const_iterator get_key_value(std::string::const_iterator & i,
0028                                           std::string::const_iterator const & end,
0029                                           std::string & key,
0030                                           std::string & value)
0031 {
0032     bool in_value = false;
0033     bool quoted = false;
0034 
0035     key.clear();
0036     value.clear();
0037 
0038     while (i != end)
0039     {
0040         if (in_value == false)
0041         {
0042             if (*i == '=')
0043             {
0044                 in_value = true;
0045                 if (i != end && *(i + 1) == '"')
0046                 {
0047                     quoted = true;
0048                     ++i; // jump over the quote
0049                 }
0050             }
0051             else if (!isspace(*i))
0052             {
0053                 key += *i;
0054             }
0055         }
0056         else
0057         {
0058             if ((quoted == true && *i == '"') || (quoted == false && isspace(*i)))
0059             {
0060                 return ++i;
0061             }
0062             else
0063             {
0064                 value += *i;
0065             }
0066         }
0067         ++i;
0068     }
0069     return i;
0070 }
0071 
0072 // decode charset and ncharset names
0073 int charset_code(const std::string & name)
0074 {
0075     // Note: unofficial reference for charset ids is:
0076     // http://www.mydul.net/charsets.html
0077 
0078     int code;
0079 
0080     if (name == "utf8")
0081     {
0082         code = 871;
0083     }
0084     else if (name == "utf16")
0085     {
0086         code = OCI_UTF16ID;
0087     }
0088     else if (name == "we8mswin1252" || name == "win1252")
0089     {
0090         code = 178;
0091     }
0092     else
0093     {
0094         // allow explicit number value
0095 
0096         std::istringstream ss(name);
0097 
0098         ss >> code;
0099         if (!ss)
0100         {
0101             throw soci_error("Invalid character set name.");
0102         }
0103     }
0104 
0105     return code;
0106 }
0107 
0108 // retrieves service name, user name and password from the
0109 // uniform connect string
0110 void chop_connect_string(std::string const & connectString,
0111     std::string & serviceName, std::string & userName,
0112     std::string & password, int & mode, bool & decimals_as_strings,
0113     int & charset, int & ncharset)
0114 {
0115     serviceName.clear();
0116     userName.clear();
0117     password.clear();
0118     mode = OCI_DEFAULT;
0119     decimals_as_strings = false;
0120     charset = 0;
0121     ncharset = 0;
0122 
0123     std::string key, value;
0124     std::string::const_iterator i = connectString.begin();
0125     while (i != connectString.end())
0126     {
0127         i = get_key_value(i, connectString.end(), key, value);
0128         if (key == "service")
0129         {
0130             serviceName = value;
0131         }
0132         else if (key == "user")
0133         {
0134             userName = value;
0135         }
0136         else if (key == "password")
0137         {
0138             password = value;
0139         }
0140         else if (key == "mode")
0141         {
0142             if (value == "sysdba")
0143             {
0144                 mode = OCI_SYSDBA;
0145             }
0146             else if (value == "sysoper")
0147             {
0148                 mode = OCI_SYSOPER;
0149             }
0150             else if (value == "default")
0151             {
0152                 mode = OCI_DEFAULT;
0153             }
0154             else
0155             {
0156                 throw soci_error("Invalid connection mode.");
0157             }
0158         }
0159         else if (key == "decimals_as_strings")
0160         {
0161             decimals_as_strings = value == "1" || value == "Y" || value == "y";
0162         }
0163         else if (key == "charset")
0164         {
0165             charset = charset_code(value);
0166         }
0167         else if (key == "ncharset")
0168         {
0169             ncharset = charset_code(value);
0170         }
0171     }
0172 }
0173 
0174 // concrete factory for Empty concrete strategies
0175 oracle_session_backend * oracle_backend_factory::make_session(
0176      connection_parameters const & parameters) const
0177 {
0178     std::string serviceName, userName, password;
0179     int mode;
0180     bool decimals_as_strings;
0181     int charset;
0182     int ncharset;
0183 
0184     chop_connect_string(parameters.get_connect_string(), serviceName, userName, password,
0185         mode, decimals_as_strings, charset, ncharset);
0186 
0187     return new oracle_session_backend(serviceName, userName, password,
0188         mode, decimals_as_strings, charset, ncharset);
0189 }
0190 
0191 oracle_backend_factory const soci::oracle;
0192 
0193 extern "C"
0194 {
0195 
0196 // for dynamic backend loading
0197 SOCI_ORACLE_DECL backend_factory const * factory_oracle()
0198 {
0199     return &soci::oracle;
0200 }
0201 
0202 SOCI_ORACLE_DECL void register_factory_oracle()
0203 {
0204     soci::dynamic_backends::register_backend("oracle", soci::oracle);
0205 }
0206 
0207 } // extern "C"