Changeset: bab82f70e0ca for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/bab82f70e0ca Added Files: clients/odbc/driver/ODBCAttrs.h Modified Files: clients/odbc/driver/CMakeLists.txt clients/odbc/driver/ODBCDbc.c clients/odbc/driver/ODBCDbc.h clients/odbc/driver/SQLConnect.c Branch: odbc-tls Log Message:
Move all odbc parameters into msettings Currently, uid, password, database, host, port, etc., all get passed around and processed separately. Now that we have lots of extra TLS parameters, plus schema, time zone, etc, this is no longer sustainable. This is a huge delta but I couldn't find a way to split it., diffs (truncated from 661 to 300 lines): diff --git a/clients/odbc/driver/CMakeLists.txt b/clients/odbc/driver/CMakeLists.txt --- a/clients/odbc/driver/CMakeLists.txt +++ b/clients/odbc/driver/CMakeLists.txt @@ -19,6 +19,7 @@ add_library(MonetODBC target_sources(MonetODBC PRIVATE + ODBCAttrs.h ODBCConvert.c ODBCDbc.c ODBCDbc.h diff --git a/clients/odbc/driver/ODBCAttrs.h b/clients/odbc/driver/ODBCAttrs.h new file mode 100644 --- /dev/null +++ b/clients/odbc/driver/ODBCAttrs.h @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2024 MonetDB Foundation; + * Copyright August 2008 - 2023 MonetDB B.V.; + * Copyright 1997 - July 2008 CWI. + */ + +/* + * Provide a mapping between attribute names as found in data sources and + * connection strings. +*/ + +#ifndef ODBCATTRS +#define ODBCATTRS + +#include "msettings.h" + +struct attr_setting { + const char *name; // canonical attribute name + const char *alt_name; // user-facing attribute name + mparm parm; +}; + +// defined in SQLConnect.c, also used in SQLBrowseConnect.c +extern const struct attr_setting attr_settings[]; +extern const int attr_setting_count; + +// look up attr_setting entry by name or alt_name, -1 if not found +int attr_setting_lookup(const char *attr_name); + + + + +#endif diff --git a/clients/odbc/driver/ODBCDbc.c b/clients/odbc/driver/ODBCDbc.c --- a/clients/odbc/driver/ODBCDbc.c +++ b/clients/odbc/driver/ODBCDbc.c @@ -48,11 +48,21 @@ ODBCDbc * newODBCDbc(ODBCEnv *env) { ODBCDbc *dbc; + msettings *settings; assert(env); dbc = (ODBCDbc *) malloc(sizeof(ODBCDbc)); - if (dbc == NULL) { + settings = msettings_create(); + + if ( + dbc == NULL + || settings == NULL + || msetting_set_string(settings, MP_USER, "monetdb") != NULL + || msetting_set_string(settings, MP_PASSWORD, "monetdb") != NULL + ) { + free(dbc); + msettings_destroy(settings); /* Memory allocation error */ addEnvError(env, "HY001", NULL, 0); return NULL; @@ -60,6 +70,7 @@ newODBCDbc(ODBCEnv *env) *dbc = (ODBCDbc) { .Env = env, + .settings = settings, .sql_attr_autocommit = SQL_AUTOCOMMIT_ON, /* default is autocommit */ .sql_attr_metadata_id = SQL_FALSE, /* add this dbc to start of the administrative linked dbc list */ @@ -173,16 +184,12 @@ destroyODBCDbc(ODBCDbc *dbc) /* cleanup own managed data */ deleteODBCErrorList(&dbc->Error); - if (dbc->dsn) - free(dbc->dsn); - if (dbc->uid) - free(dbc->uid); - if (dbc->pwd) - free(dbc->pwd); - if (dbc->host) - free(dbc->host); - if (dbc->dbname) - free(dbc->dbname); + msettings_destroy(dbc->settings); + free(dbc->dsn); + free(dbc->uid); + free(dbc->pwd); + free(dbc->host); + free(dbc->dbname); free(dbc); } 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 @@ -39,6 +39,7 @@ #include "ODBCEnv.h" #include "ODBCError.h" #include "mapi.h" +#include "msettings.h" typedef struct tODBCDRIVERDBC { @@ -51,6 +52,7 @@ typedef struct tODBCDRIVERDBC { int RetrievedErrors; /* # of errors already retrieved by SQLError */ /* connection information */ + msettings *settings; /* All connection parameters */ char *dsn; /* Data source name or NULL */ char *uid; /* User ID or NULL */ char *pwd; /* Password for User ID or NULL */ 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 @@ -32,6 +32,7 @@ #include "ODBCGlobal.h" #include "ODBCDbc.h" #include "ODBCUtil.h" +#include "ODBCAttrs.h" #include <time.h> #include "msettings.h" #include "mstring.h" @@ -44,6 +45,42 @@ #define SQLGetPrivateProfileString(section,entry,default,buffer,bufferlen,filename) ((int) strcpy_len(buffer,default,bufferlen)) #endif + +const struct attr_setting attr_settings[] = { + { "uid", "User", MP_USER }, + { "pwd", "Password", MP_PASSWORD }, + { "database", "Database", MP_DATABASE }, + { "port", "Port", MP_PORT }, + { "host", "Host", MP_HOST }, + { "sock", "Unix Socket", MP_SOCK }, + { "tls", "Encrypt", MP_TLS }, + { "cert", "Server Certificate", MP_CERT }, + { "certhash", "Server Certificate Hash", MP_CERTHASH }, + { "clientkey", "Client Key", MP_CLIENTKEY }, + { "clientcert", "Client Certificate", MP_CLIENTCERT }, + { "autocommit", "Autocommit", MP_AUTOCOMMIT }, + { "schema", "Schema", MP_SCHEMA }, + { "timezone", "Time Zone", MP_TIMEZONE }, + { "replysize", "Reply Size", MP_REPLYSIZE }, + { "logfile", "Log File", MP_LOGFILE }, +}; + +const int attr_setting_count = sizeof(attr_settings) / sizeof(attr_settings[0]); + +int +attr_setting_lookup(const char *attr_name) +{ + for (int i = 0; i < attr_setting_count; i++) { + const struct attr_setting *entry = &attr_settings[i]; + if (strcasecmp(attr_name, entry->name) == 0) + return i; + if (entry->alt_name && strcasecmp(attr_name, entry->alt_name) == 0) + return i; + } + return -1; +} + + static void get_serverinfo(ODBCDbc *dbc) { @@ -84,84 +121,146 @@ get_serverinfo(ODBCDbc *dbc) mapi_close_handle(hdl); } -// Return a newly allocated NUL-terminated config value from either the argument -// or the data source. Return 'default_value' if no value can be found, NULL on -// allocation error. + +// Ensure '*argument' is either NULL or a NUL-terminated string, +// taking into account 'argument_len' being either a proper string length +// or one of the special values SQL_NULL_DATA or SQL_NTS. // -// If non-NULL, parameter 'argument' points to an argument that may or may not -// be NUL-terminated. The length parameter 'argument_len' can either be the -// length of the argument or one of the following special values: +// Return 'true' on success and 'false' on allocation failure. // -// SQL_NULL_DATA: consider the argument NULL -// SQL_NTS: the argument is actually NUL-terminated +// If memory needs to be allocated and 'scratch' is not NULL, +// a pointer to the allocated memory will be stored in '*scratch' +// and the previous value of '*scratch' will be free'd. // -// Parameters 'dsn' and 'entry', if not NULL and not empty, indicate which data -// source field to look up in "odbc.ini". +// '*argument' is never free'd. +static bool +make_nul_terminated(const SQLCHAR **argument, ssize_t argument_len, void **scratch) +{ + assert(argument != NULL); + + if (*argument == NULL || argument_len == SQL_NTS) + return true; + if (argument_len == SQL_NULL_DATA) { + *argument = NULL; + return true; + } + + SQLCHAR *value = malloc(argument_len + 1); + if (value == NULL) + return false; + memmove(value, argument, argument_len); + value[argument_len] = '\0'; + + *argument = value; + if (scratch) { + free(*scratch); + *scratch = value; + } + + return value; +} + +#ifdef ODBCDEBUG static char* -getConfig( - const void *argument, ssize_t argument_len, - const char *dsn, const char *entry, - const char *default_value) +display_connect_string(const char *dsn, const msettings *settings) { - if (argument != NULL && argument_len != SQL_NULL_DATA) { - // argument is present.. - if (argument_len == SQL_NTS) { - // .. and it's already NUL-terminated - return strdup((const char*)argument); + + size_t pos = 0; + size_t cap = 1024; + char *buf = malloc(cap); // reallocprintf will deal with allocation failures + char *sep = ""; + char *value = NULL; + char *default_value = NULL; + bool ok = false; + + if (dsn) { + if (reallocprintf(&buf, &pos, &cap, "DSN=%s", dsn) < 0) + goto end; + sep = "; "; + } + + for (int i = 0; i < attr_setting_count; i++) { + const struct attr_setting *entry = &attr_settings[i]; + mparm parm = entry->parm; + + if (parm == MP_TABLE || parm == MP_TABLESCHEMA) + continue; + + free(value); + value = msetting_as_string(settings, parm); + if (!value) + goto end; + + bool show_this = true; + if (parm == MP_USER || parm == MP_PASSWORD) { + show_this = true; + } else if (parm == MP_PORT && msetting_long(settings, MP_PORT) <= 0) { + show_this = false; + } else if (parm == MP_TLS) { + show_this = msetting_bool(settings, MP_TLS); + } else if (mparm_is_core(parm)) { + show_this = true; } else { - // .. but we need to create a NUL-terminated copy - char *value = malloc(argument_len + 1); - if (value == NULL) - return NULL; - memmove(value, argument, argument_len); - value[argument_len] = '\0'; - return value; + // skip if still default + free(default_value); + default_value = msetting_as_string(msettings_default, parm); + if (!default_value) + goto end; _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org