Changeset: 266b6c8a0632 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/266b6c8a0632
Modified Files:
clients/odbc/driver/ODBCDbc.h
clients/odbc/driver/SQLBrowseConnect.c
clients/odbc/driver/SQLConnect.c
clients/odbc/driver/SQLDriverConnect.c
clients/odbc/driver/SQLExecute.c
clients/odbc/driver/SQLPrepare.c
Branch: default
Log Message:
Added ODBC connection string parameter: mapToLongVarchar=<posint>
Specifies the length of a string at which to begin mapping string values to
an ODBC SQL_WLONGVARCHAR data type instead of the default ODBC SQL_WVARCHAR
data type.
0 (or unset): Maps string values in their default ODBC data types. Default
= 0.
> 0: Specifies the maximum number of string characters to map to default
ODBC string data types. All strings larger than this value are mapped to
SQL_WLONGVARCHAR.
You can also specify this parameter only as a connection parameter.
Note: This is a used to workaround an MS SQL Server linked server limitation
which can not deal with varchars larger than 4000.
diffs (249 lines):
diff --git a/clients/odbc/driver/ODBCDbc.h b/clients/odbc/driver/ODBCDbc.h
--- a/clients/odbc/driver/ODBCDbc.h
+++ b/clients/odbc/driver/ODBCDbc.h
@@ -59,6 +59,7 @@ typedef struct tODBCDRIVERDBC {
bool has_comment; /* whether the server has sys.comments */
bool allow_hugeint; /* whether the application deals with HUGEINT */
bool raw_strings; /* server uses raw strings */
+ int mapToLongVarchar; /* when > 0 we map WVARCHAR to WLONGVARCHAR,
default 0 */
SQLUINTEGER sql_attr_autocommit;
SQLUINTEGER sql_attr_metadata_id;
SQLUINTEGER sql_attr_connection_timeout;
@@ -148,9 +149,13 @@ SQLRETURN ODBCConnectionString(SQLRETURN
SQLSMALLINT *StringLength2Ptr,
const char *dsn, const char *uid,
const char *pwd, const char *host,
- int port, const char *database);
+ int port, const char *database,
+ int mapToLongVarchar);
SQLRETURN MNDBAllocStmt(ODBCDbc *dbc, SQLHANDLE *pnOutputHandle);
-SQLRETURN MNDBConnect(ODBCDbc *dbc, const SQLCHAR *szDataSource, SQLSMALLINT
nDataSourceLength, const SQLCHAR *szUID, SQLSMALLINT nUIDLength, const SQLCHAR
*szPWD, SQLSMALLINT nPWDLength, const char *host, int port, const char *schema);
+SQLRETURN MNDBConnect(ODBCDbc *dbc, const SQLCHAR *szDataSource, SQLSMALLINT
nDataSourceLength,
+ const SQLCHAR *szUID, SQLSMALLINT nUIDLength,
+ const SQLCHAR *szPWD, SQLSMALLINT nPWDLength,
+ const char *host, int port, const char *dbname, int
mapToLongVarchar);
SQLRETURN MNDBGetConnectAttr(ODBCDbc *dbc, SQLINTEGER Attribute, SQLPOINTER
ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLength);
SQLRETURN MNDBSetConnectAttr(ODBCDbc *dbc, SQLINTEGER Attribute, SQLPOINTER
ValuePtr, SQLINTEGER StringLength);
diff --git a/clients/odbc/driver/SQLBrowseConnect.c
b/clients/odbc/driver/SQLBrowseConnect.c
--- a/clients/odbc/driver/SQLBrowseConnect.c
+++ b/clients/odbc/driver/SQLBrowseConnect.c
@@ -53,7 +53,7 @@ MNDBBrowseConnect(ODBCDbc *dbc,
{
char *key, *attr;
char *dsn, *uid, *pwd, *host, *dbname;
- int port;
+ int port, mapToLongVarchar;
SQLSMALLINT len = 0;
char buf[1024];
int n;
@@ -81,6 +81,7 @@ MNDBBrowseConnect(ODBCDbc *dbc,
host = dbc->host ? strdup(dbc->host) : NULL;
port = dbc->port;
dbname = dbc->dbname ? strdup(dbc->dbname) : NULL;
+ mapToLongVarchar = dbc->mapToLongVarchar;
while ((n = ODBCGetKeyAttr(&InConnectionString, &StringLength1, &key,
&attr)) > 0) {
if (strcasecmp(key, "dsn") == 0 && dsn == NULL) {
@@ -106,6 +107,9 @@ MNDBBrowseConnect(ODBCDbc *dbc,
if (dbname)
free(dbname);
dbname = attr;
+ } else if (strcasecmp(key, "mapToLongVarchar") == 0 &&
mapToLongVarchar == 0) {
+ mapToLongVarchar = atoi(attr);
+ free(attr);
#ifdef ODBCDEBUG
} else if (strcasecmp(key, "logfile") == 0 &&
#ifdef NATIVE_WIN32
@@ -218,13 +222,17 @@ MNDBBrowseConnect(ODBCDbc *dbc,
}
if (uid != NULL && pwd != NULL) {
- rc = MNDBConnect(dbc, (SQLCHAR *) dsn, SQL_NTS, (SQLCHAR *)
uid, SQL_NTS, (SQLCHAR *) pwd, SQL_NTS, host, port, dbname);
+ rc = MNDBConnect(dbc, (SQLCHAR *) dsn, SQL_NTS,
+ (SQLCHAR *) uid, SQL_NTS,
+ (SQLCHAR *) pwd, SQL_NTS,
+ host, port, dbname,
+ mapToLongVarchar);
if (SQL_SUCCEEDED(rc)) {
rc = ODBCConnectionString(rc, dbc, OutConnectionString,
BufferLength,
StringLength2Ptr,
dsn, uid, pwd, host, port,
- dbname);
+ dbname, mapToLongVarchar);
}
} else {
len = (SQLSMALLINT) strconcat_len(
diff --git a/clients/odbc/driver/SQLConnect.c b/clients/odbc/driver/SQLConnect.c
--- a/clients/odbc/driver/SQLConnect.c
+++ b/clients/odbc/driver/SQLConnect.c
@@ -90,7 +90,8 @@ MNDBConnect(ODBCDbc *dbc,
SQLSMALLINT NameLength3,
const char *host,
int port,
- const char *dbname)
+ const char *dbname,
+ int mapToLongVarchar)
{
SQLRETURN rc = SQL_SUCCESS;
char *dsn = NULL;
@@ -276,6 +277,7 @@ MNDBConnect(ODBCDbc *dbc,
if (dbc->dbname != NULL)
free(dbc->dbname);
dbc->dbname = (char *) dbname; /* discard const */
+ dbc->mapToLongVarchar = mapToLongVarchar;
get_serverinfo(dbc);
/* set timeout after we're connected */
mapi_timeout(mid, dbc->sql_attr_connection_timeout * 1000);
@@ -306,7 +308,7 @@ SQLConnect(SQLHDBC ConnectionHandle,
ServerName, NameLength1,
UserName, NameLength2,
Authentication, NameLength3,
- NULL, 0, NULL);
+ NULL, 0, NULL, 0);
}
SQLRETURN SQL_API
@@ -357,7 +359,7 @@ SQLConnectW(SQLHDBC ConnectionHandle,
ds, SQL_NTS,
uid, SQL_NTS,
pwd, SQL_NTS,
- NULL, 0, NULL);
+ NULL, 0, NULL, 0);
bailout:
if (ds)
diff --git a/clients/odbc/driver/SQLDriverConnect.c
b/clients/odbc/driver/SQLDriverConnect.c
--- a/clients/odbc/driver/SQLDriverConnect.c
+++ b/clients/odbc/driver/SQLDriverConnect.c
@@ -113,7 +113,8 @@ ODBCConnectionString(SQLRETURN rc,
const char *pwd,
const char *host,
int port,
- const char *database)
+ const char *database,
+ int mapToLongVarchar)
{
int n;
#ifdef ODBCDEBUG
@@ -188,8 +189,19 @@ ODBCConnectionString(SQLRETURN rc,
if (database) {
if (BufferLength > 0) {
n = snprintf((char *) OutConnectionString,
- BufferLength,
- "DATABASE=%s;", database);
+ BufferLength, "DATABASE=%s;", database);
+ if (n < 0)
+ n = BufferLength + 1;
+ BufferLength -= n;
+ OutConnectionString += n;
+ } else {
+ BufferLength = -1;
+ }
+ }
+ if (mapToLongVarchar > 0) {
+ if (BufferLength > 0) {
+ n = snprintf((char *) OutConnectionString,
+ BufferLength, "mapToLongVarchar=%d;",
mapToLongVarchar);
if (n < 0)
n = BufferLength + 1;
BufferLength -= n;
@@ -293,7 +305,7 @@ MNDBDriverConnect(ODBCDbc *dbc,
{
char *key, *attr;
char *dsn = 0, *uid = 0, *pwd = 0, *host = 0, *database = 0;
- int port = 0;
+ int port = 0, mapToLongVarchar = 0;
SQLRETURN rc;
int n;
@@ -343,6 +355,9 @@ MNDBDriverConnect(ODBCDbc *dbc,
else if (strcasecmp(key, "port") == 0 && port == 0) {
port = atoi(attr);
free(attr);
+ } else if (strcasecmp(key, "mapToLongVarchar") == 0 &&
mapToLongVarchar == 0) {
+ mapToLongVarchar = atoi(attr);
+ free(attr);
#ifdef ODBCDEBUG
#ifdef NATIVE_WIN32
} else if (strcasecmp(key, "logfile") == 0 &&
@@ -389,13 +404,15 @@ MNDBDriverConnect(ODBCDbc *dbc,
rc = MNDBConnect(dbc, (SQLCHAR *) dsn, SQL_NTS,
(SQLCHAR *) uid, SQL_NTS,
(SQLCHAR *) pwd, SQL_NTS,
- host, port, database);
+ host, port, database,
+ mapToLongVarchar);
}
if (SQL_SUCCEEDED(rc)) {
rc = ODBCConnectionString(rc, dbc, OutConnectionString,
BufferLength, StringLength2Ptr,
- dsn, uid, pwd, host, port, database);
+ dsn, uid, pwd, host, port, database,
+ mapToLongVarchar);
}
if (dsn)
diff --git a/clients/odbc/driver/SQLExecute.c b/clients/odbc/driver/SQLExecute.c
--- a/clients/odbc/driver/SQLExecute.c
+++ b/clients/odbc/driver/SQLExecute.c
@@ -48,7 +48,7 @@ static struct msql_types {
{"hugeint", SQL_HUGEINT},
/* {"inet", SQL_WCHAR}, */
{"int", SQL_INTEGER},
- /* {"json", SQL_WCHAR}, */
+ /* {"json", SQL_WVARCHAR}, */
{"month_interval", SQL_INTERVAL_MONTH},
{"oid", SQL_BIGINT},
{"real", SQL_REAL},
@@ -60,7 +60,7 @@ static struct msql_types {
{"timestamp", SQL_TYPE_TIMESTAMP},
{"timestamptz", SQL_TYPE_TIMESTAMP},
{"tinyint", SQL_TINYINT},
- /* {"url", SQL_WCHAR}, */
+ /* {"url", SQL_WVARCHAR}, */
{"uuid", SQL_GUID},
{"varchar", SQL_WVARCHAR},
{0, 0}, /* sentinel */
@@ -388,6 +388,15 @@ ODBCInitResult(ODBCStmt *stmt)
* that */
rec->sql_desc_display_size = mapi_get_len(hdl, i);
rec->sql_desc_octet_length = 4 *
rec->sql_desc_display_size;
+
+ /* For large varchar column definitions conditionally
+ * change type to SQL_WLONGVARCHAR when
mapToLongVarchar is set (e.g. to 4000)
+ * This is a workaround for MS SQL Server linked server
+ * which can not handle large varchars (ref:
SUPPORT-747) */
+ if (rec->sql_desc_concise_type == SQL_WVARCHAR
+ && stmt->Dbc->mapToLongVarchar > 0
+ && rec->sql_desc_length > (SQLULEN)
stmt->Dbc->mapToLongVarchar)
+ rec->sql_desc_concise_type = SQL_WLONGVARCHAR;
} else {
rec->sql_desc_length = ODBCLength(rec, SQL_DESC_LENGTH);
rec->sql_desc_display_size = ODBCLength(rec,
SQL_DESC_DISPLAY_SIZE);
diff --git a/clients/odbc/driver/SQLPrepare.c b/clients/odbc/driver/SQLPrepare.c
--- a/clients/odbc/driver/SQLPrepare.c
+++ b/clients/odbc/driver/SQLPrepare.c
@@ -277,9 +277,18 @@ MNDBPrepare(ODBCStmt *stmt,
rec->sql_desc_concise_type == SQL_LONGVARCHAR ||
rec->sql_desc_concise_type == SQL_WCHAR ||
rec->sql_desc_concise_type == SQL_WVARCHAR ||
- rec->sql_desc_concise_type == SQL_WLONGVARCHAR)
+ rec->sql_desc_concise_type == SQL_WLONGVARCHAR) {
rec->sql_desc_case_sensitive = SQL_TRUE;
- else
+
+ /* For large varchar column definitions conditionally
+ * change type to SQL_WLONGVARCHAR when
mapToLongVarchar is set (e.g. to 4000)
+ * This is a workaround for MS SQL Server linked server
+ * which can not handle large varchars (ref:
SUPPORT-747) */
+ if (rec->sql_desc_concise_type == SQL_WVARCHAR
+ && stmt->Dbc->mapToLongVarchar > 0
+ && rec->sql_desc_length > (SQLULEN)
stmt->Dbc->mapToLongVarchar)
+ rec->sql_desc_concise_type = SQL_WLONGVARCHAR;
+ } else
rec->sql_desc_case_sensitive = SQL_FALSE;
rec->sql_desc_local_type_name = NULL;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]