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"