Date: Thursday, March 30, 2006 @ 21:23:52
Author: marc
Path: /cvsroot/carob/odbsequoia
Modified: odbcinst.ini (1.2 -> 1.3) src/connect.cpp (1.21 -> 1.22)
src/env.cpp (1.10 -> 1.11) src/env.hpp (1.5 -> 1.6) src/inst.hpp
(1.6 -> 1.7)
Now letting empty ODBC.INI values go through carob (and fail with a more
detailed error)
Implemented FakeODBC2 in odbcinst.ini, fixes ODBSEQ-20
Documented cryptic SQLGetPrivateProfileString() in inst.hpp
-----------------+
odbcinst.ini | 1 +
src/connect.cpp | 33 +++++++++++++++++----------------
src/env.cpp | 24 +++++++++++++++++++++---
src/env.hpp | 4 +++-
src/inst.hpp | 39 +++++++++++++++++++++++++++++++++++++++
5 files changed, 81 insertions(+), 20 deletions(-)
Index: odbsequoia/odbcinst.ini
diff -u odbsequoia/odbcinst.ini:1.2 odbsequoia/odbcinst.ini:1.3
--- odbsequoia/odbcinst.ini:1.2 Thu Mar 23 00:32:29 2006
+++ odbsequoia/odbcinst.ini Thu Mar 30 21:23:52 2006
@@ -4,3 +4,4 @@
Debug = 1
CommLog = 1
FileUsage = 1
+#FakeODBC2 = false (default = true)
Index: odbsequoia/src/connect.cpp
diff -u odbsequoia/src/connect.cpp:1.21 odbsequoia/src/connect.cpp:1.22
--- odbsequoia/src/connect.cpp:1.21 Thu Mar 30 18:53:31 2006
+++ odbsequoia/src/connect.cpp Thu Mar 30 21:23:52 2006
@@ -30,8 +30,6 @@
#include "StringCodecs.hpp"
#include "Common.hpp" // setLogLevel()
-#include <odbcinst.h>
-
#include <cstdlib> // for atoi()
@@ -88,10 +86,6 @@
LPCSTR cdsn = narrow_dsn.c_str();
#endif
- // The trick: providing a zero-length default value is like
- // providing NO default value. Now we can throw an SQL_ERROR
- // when we require the user to provide a value.
-
// TODO: call SQLInstallerError() to throw better diags
// BTW how could we fail when providing a default value?
@@ -99,36 +93,43 @@
// Slurp DSN information from odbc.ini into ConnectionParameters
+ // Behaviour of SQLGetPrivateProfileString is complex and weird,
+ // check comments in inst.hpp
+
+ // For most keys, if the user sets an empty string then zero is
+ // returned and we let carob connection fail later on. We should
+ // be stricter and throw a good diag.
+
/* Server host name/IP address */
- if (0 >= SQLGetPrivateProfileString(cdsn, SERVER_INI, "localhost",
+ if (0 > SQLGetPrivateProfileString(cdsn, SERVER_INI, "localhost",
temp, MAX_VALUE_LEN, ODBC_INI))
- return SQL_ERROR; // TODO: diags. On the other hand it can hardly fail.
+ return SQL_ERROR;
std::wstring serverhost = fromString(std::string(temp));
/* Port number */
- if (0 >= SQLGetPrivateProfileString(cdsn, PORT_INI, "25322",
+ if (0 > SQLGetPrivateProfileString(cdsn, PORT_INI, "25322",
temp, MAX_VALUE_LEN, ODBC_INI))
- return SQL_ERROR; // TODO: diags. On the other hand it can hardly fail.
+ return SQL_ERROR;
in_port_t port = atoi(temp);
- /* Virtual Database name (mandatory, no default) */
+ /* Virtual Database name (mandatory, be stricter here) */
if (0 >= SQLGetPrivateProfileString(cdsn, DATABASE_INI, "",
temp, MAX_VALUE_LEN, ODBC_INI))
throw ODBSeqException(L"08001", L"'" WIDENMACRO(DATABASE_INI) L"'"
- L" parameter not found in .ini file");
+ L" key not found or empty in "
WIDENMACRO(ODBC_INI) L" file");
std::wstring vdbname = fromString(std::string(temp));
/* Prefix for diagnostics/exceptions/warnings coming from the backend */
- if (0 >= SQLGetPrivateProfileString(cdsn, BACKEND_IDS_INI,
DEFAULT_BACKEND_IDS_INI,
+ if (0 > SQLGetPrivateProfileString(cdsn, BACKEND_IDS_INI,
DEFAULT_BACKEND_IDS_INI,
temp, MAX_VALUE_LEN, ODBC_INI))
return SQL_ERROR; // TODO: diags. On the other hand it can hardly fail.
this->backend_diagids = fromString(std::string(temp));
- /* Log level (mainly for carob) */
- if (0 >= SQLGetPrivateProfileString(cdsn, LOG_LEVEL_INI, "DEFAULTLOGLEVEL",
+ /* Log level (mainly for carob) TODO: move this to inst.ini/Env ctor */
+ if (0 > SQLGetPrivateProfileString(cdsn, LOG_LEVEL_INI,
"DEFAULTCAROBLOGLEVEL",
temp, MAX_VALUE_LEN, ODBC_INI))
return SQL_ERROR; // TODO: diags. On the other hand it can hardly fail.
- if (0 != std::string(temp).compare("DEFAULTLOGLEVEL"))
+ if (0 != std::string(temp).compare("DEFAULTCAROBLOGLEVEL"))
try {
setLogLevel(StringLogLevel(temp));
} catch (const std::string& errmsg) { // unknown log level!
Index: odbsequoia/src/env.cpp
diff -u odbsequoia/src/env.cpp:1.10 odbsequoia/src/env.cpp:1.11
--- odbsequoia/src/env.cpp:1.10 Thu Mar 30 18:53:31 2006
+++ odbsequoia/src/env.cpp Thu Mar 30 21:23:52 2006
@@ -23,6 +23,7 @@
#include "connect.hpp"
#include "odbc_exception.hpp"
+#include "inst.hpp"
#include "Common.hpp" // for the logger
@@ -34,6 +35,26 @@
using namespace ODBSeqNS;
+ODBCEnv::ODBCEnv() : ODBCItem(*this) // I have no father
+{
+#define MAX_VALUE_LEN 30
+ char temp[MAX_VALUE_LEN];
+
+ /* Fake ODBC version 2 */
+ if (0 > SQLGetPrivateProfileString(MYDRIVER_NAME_INST_INI,
FAKEODBC2_INST_INI, "true",
+ temp, MAX_VALUE_LEN, ODBCINST_INI))
+ // FIXME: catch above & return diags
+ // Problem: how to return diags without any object?
+ // But how could this fail anyway?
+ throw ODBSeqException(L"TODO",
+ L"Invalid " WIDENMACRO(FAKEODBC2_INST_INI) L"
value");
+
+ if (0 == std::string(temp).compare("false"))
+ fake_version2 = false;
+ else
+ fake_version2 = true;
+}
+
namespace {
const std::wstring SETENVATTR_FUNC = L"env.cpp:SQLSetEnvAttr";
}
@@ -69,9 +90,6 @@
std::wstring func_witharg(SETENVATTR_FUNC + L"(ODBC_VERSION, 2,
)");
- // TODO: move this constant to odbc.ini
- bool fake_version2 = true;
-
if (!fake_version2) {
std::wstring msg(L"faking ODBC version 2 is disabled");
CarobNS::logFatal(func_witharg, msg);
Index: odbsequoia/src/env.hpp
diff -u odbsequoia/src/env.hpp:1.5 odbsequoia/src/env.hpp:1.6
--- odbsequoia/src/env.hpp:1.5 Thu Mar 30 18:42:58 2006
+++ odbsequoia/src/env.hpp Thu Mar 30 21:23:52 2006
@@ -35,12 +35,14 @@
class ODBCEnv : public ODBCItem
{
public:
- ODBCEnv() : ODBCItem(*this) { }; // I have no father
+ ODBCEnv();
SQLRETURN
ODBCEnv::AllocConnect(SQLHANDLE * OutputHandle);
SQLRETURN
ODBCEnv::set_env_attr(SQLINTEGER attribute, SQLPOINTER value, SQLINTEGER
str_len);
+
+ bool fake_version2;
};
}
Index: odbsequoia/src/inst.hpp
diff -u odbsequoia/src/inst.hpp:1.6 odbsequoia/src/inst.hpp:1.7
--- odbsequoia/src/inst.hpp:1.6 Thu Mar 30 17:23:53 2006
+++ odbsequoia/src/inst.hpp Thu Mar 30 21:23:52 2006
@@ -22,6 +22,10 @@
#ifndef ODBSEQ_INST
#define ODBSEQ_INST
+
+#include <odbcinst.h>
+
+
/* ODBC initialization files */
#ifndef WIN32
#define ODBC_INI "odbc.ini"
@@ -31,7 +35,42 @@
#define ODBCINST_INI "ODBCINST.INI"
#endif
+#define MYDRIVER_NAME_INST_INI "Sequoia"
+
+
+// unixODBC 2.2 SQLGetPrivateProfileString() tips:
+
+// - in ODBCINST.INI -
+
+// Here SQLGetPrivateProfileString(INST) returns strlen(value) + 1,
+// INCLUDING the terminating null, whatever the lpszDefault
+// arg. Corner cases:
+
+// < 0 on error (?)
+// 0 when key is missing (and lpszDefault is set)
+// 1 when value is missing (= empty string + terminating null)
+
+// The default value is set only when 0 is returned (so the user can
+// explicitely set an empty value if wanted).
+
+// - in ODBC.INI -
+
+// For more fun, the behaviour now differs: it returns strlen(value),
+// EXCLUDING the terminating null. And it returns strlen(lpszDefault)
+// when the key is missing. So it's now absolutely impossible to make
+// the difference between a value explicity set in the file and the
+// case missing key && lpszDefault set. Empty string value is still not
+// an issue.
+
+
+// These key names are not case-sensitive with unixODBC 2.2.
+// However the associated values are returned case-untouched.
+// Others DMs?
+
+// ODBINST.INI constants
+#define FAKEODBC2_INST_INI "FakeODBC2"
+// ODBC.INI constants
#define SERVER_INI "Servername"
#define DATABASE_INI "Database"
#define USERNAME_INI "UserName"
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits