in driver/connect.c [1234:1655]
SQLRETURN config_dbc(esodbc_dbc_st *dbc, esodbc_dsn_attrs_st *attrs)
{
const static wstr_st http_prefix = WSTR_INIT("http://");
const static wstr_st https_prefix = WSTR_INIT("https://");
wstr_st prefix;
int cnt, ipv6, n;
SQLBIGINT secure, timeout, max_body_size, max_fetch_size, varchar_limit;
SQLWCHAR buff_url[ESODBC_MAX_URL_LEN];
wstr_st url = (wstr_st) {
buff_url, /*will be init'ed later*/0
};
/*
* setup logging
*/
if (! config_dbc_logging(dbc, attrs)) {
/* attempt global logging the error */
ERRH(dbc, "failed to setup DBC logging");
goto err;
}
if (attrs->cloud_id.cnt && (! decode_cloud_id(dbc, attrs))) {
goto err;
} else if (http_prefix.cnt <= attrs->server.cnt) {
/* make sure that user didn't input a HTTP URL (common mistake):
* the error libcurl returns is not particularly descriptive */
do {
prefix = attrs->server;
prefix.cnt = http_prefix.cnt;
if (! EQ_CASE_WSTR(&prefix, &http_prefix)) {
if (attrs->server.cnt < https_prefix.cnt) {
break;
}
prefix.cnt = https_prefix.cnt;
if (! EQ_CASE_WSTR(&prefix, &https_prefix)) {
break;
}
}
ERRH(dbc, "hostname `" LWPDL "` can't be a HTTP(S) URL.",
LWSTR(&attrs->server));
SET_HDIAG(dbc, SQL_STATE_HY000, "The Hostname can't be a HTTP(S) "
"URL: remove the 'http(s)://' prefix (and port suffix, "
"if present).", 0);
goto err;
} while (0);
}
if (str2bigint(&attrs->secure, /*wide?*/TRUE, &secure, /*stri*/TRUE) < 0) {
ERRH(dbc, "failed to read secure param `" LWPDL "`.",
LWSTR(&attrs->secure));
SET_HDIAG(dbc, SQL_STATE_HY000, "security setting number "
"conversion failure", 0);
goto err;
}
if (secure < ESODBC_SEC_NONE || ESODBC_SEC_MAX <= secure) {
ERRH(dbc, "invalid secure param `" LWPDL "` (not within %d - %d).",
LWSTR(&attrs->secure), ESODBC_SEC_NONE, ESODBC_SEC_MAX - 1);
SET_HDIAG(dbc, SQL_STATE_HY000, "invalid security setting", 0);
goto err;
} else {
dbc->secure = (int)secure;
INFOH(dbc, "connection security level: %ld.", dbc->secure);
}
if (secure) {
if (! wstr_to_utf8(&attrs->ca_path, &dbc->ca_path)) {
ERRH(dbc, "failed to convert CA path `" LWPDL "` to UTF8.",
LWSTR(&attrs->ca_path));
SET_HDIAG(dbc, SQL_STATE_HY000, "reading the CA file path "
"failed", 0);
goto err;
}
INFOH(dbc, "CA path: `%s`.", dbc->ca_path.str);
}
/*
* SQL close and query URL of the cluster
*/
/* Note: libcurl won't check hostname validity, it'll just try to resolve
* whatever it receives, if it can parse the URL */
ipv6 = wcsnstr(attrs->server.str, attrs->server.cnt, L':') != NULL;
cnt = swprintf(url.str, sizeof(buff_url)/sizeof(*buff_url),
L"http" WPFCP_DESC "://"
WPFCP_DESC WPFWP_LDESC WPFCP_DESC ":" WPFWP_LDESC
ELASTIC_SQL_PATH /*+*/ ELASTIC_SQL_CLOSE_SUBPATH,
secure ? "s" : "",
ipv6 ? "[" : "", LWSTR(&attrs->server), ipv6 ? "]" : "",
LWSTR(&attrs->port));
if (cnt <= 0) {
ERRNH(dbc, "failed to print SQL URL out of server: `" LWPDL "`, "
"port: `" LWPDL "`.", LWSTR(&attrs->server), LWSTR(&attrs->port));
SET_HDIAG(dbc, SQL_STATE_HY000, "printing server's SQL URL failed", 0);
goto err;
} else {
url.cnt = (size_t)cnt;
}
if (! wstr_to_utf8(&url, &dbc->close_url)) {
ERRH(dbc, "failed to convert URL `" LWPDL "` to UTF8.", LWSTR(&url));
SET_HDIAG(dbc, SQL_STATE_HY000, "server SQL URL's UTF8 conversion "
"failed", 0);
goto err;
}
INFOH(dbc, "connection SQL cusor closing URL: `%s`.", dbc->close_url.str);
/* shorten the length of string in buffer, before dup'ing; it needs to be
* dup'ed since libcurl needs the 0 terminator */
url.cnt -= sizeof(ELASTIC_SQL_CLOSE_SUBPATH) - /*\0*/1;
if (! wstr_to_utf8(&url, &dbc->url)) {
ERRH(dbc, "failed to convert URL `" LWPDL "` to UTF8.", LWSTR(&url));
SET_HDIAG(dbc, SQL_STATE_HY000, "server SQL URL's UTF8 conversion "
"failed", 0);
goto err;
}
INFOH(dbc, "connection SQL query URL: `%s`.", dbc->url.str);
/*
* Root URL of the cluster
*/
cnt = swprintf(url.str, sizeof(buff_url)/sizeof(*buff_url),
L"http" WPFCP_DESC "://"
WPFCP_DESC WPFWP_LDESC WPFCP_DESC ":" WPFWP_LDESC "/",
secure ? "s" : "",
ipv6 ? "[" : "", LWSTR(&attrs->server), ipv6 ? "]" : "",
LWSTR(&attrs->port));
if (cnt <= 0) {
ERRNH(dbc, "failed to print root URL out of server: `" LWPDL "`,"
" port: `" LWPDL "`.", LWSTR(&attrs->server), LWSTR(&attrs->port));
SET_HDIAG(dbc, SQL_STATE_HY000, "printing server's URL failed", 0);
goto err;
} else {
url.cnt = (size_t)cnt;
}
if (! wstr_to_utf8(&url, &dbc->root_url)) {
ERRH(dbc, "failed to convert URL `" LWPDL "` to UTF8.", LWSTR(&url));
SET_HDIAG(dbc, SQL_STATE_HY000, "server root URL's UTF8 conversion "
"failed", 0);
goto err;
}
INFOH(dbc, "connection root URL: `%s`.", dbc->root_url.str);
/*
* credentials
*/
if (attrs->uid.cnt) {
if (! wstr_to_utf8(&attrs->uid, &dbc->uid)) {
ERRH(dbc, "failed to convert username [%zu] `" LWPDL "` to UTF8.",
attrs->uid.cnt, LWSTR(&attrs->uid));
SET_HDIAG(dbc, SQL_STATE_HY000, "username UTF8 conversion "
"failed", 0);
goto err;
}
INFOH(dbc, "connection UID: `%s`.", dbc->uid.str);
if (attrs->pwd.cnt) {
if (! wstr_to_utf8(&attrs->pwd, &dbc->pwd)) {
ERRH(dbc, "failed to convert password [%zu] `%s` to "
"UTF8.", attrs->pwd.cnt, ESODBC_PWD_VAL_SUBST);
SET_HDIAG(dbc, SQL_STATE_HY000, "password UTF8 "
"conversion failed", 0);
goto err;
}
/* indicates the presence of a non-empty password */
INFOH(dbc, "connection PWD: " ESODBC_PWD_VAL_SUBST ".");
}
} else if (attrs->api_key.cnt) {
if (! wstr_to_utf8(&attrs->api_key, &dbc->api_key)) {
ERRH(dbc, "failed to convert API key [%zu] `" LWPDL "` to UTF8.",
attrs->api_key.cnt, LWSTR(&attrs->api_key));
SET_HDIAG(dbc, SQL_STATE_HY000, "API key UTF8 conversion failed",
0);
goto err;
}
}
/* "follow location" param for liburl */
dbc->follow = wstr2bool(&attrs->follow);
INFOH(dbc, "follow: %s.", dbc->follow ? "true" : "false");
/*
* request timeout for liburl: negative reset to 0
*/
if (str2bigint(&attrs->timeout, /*wide?*/TRUE, &timeout,
/*strict*/TRUE) < 0) {
ERRH(dbc, "failed to convert `" LWPDL "` [%zu] to big int.",
LWSTR(&attrs->timeout), attrs->timeout.cnt);
SET_HDIAG(dbc, SQL_STATE_HY000, "timeout setting number "
"conversion failure", 0);
goto err;
}
if (ULONG_MAX <= timeout || timeout < 0) {
WARNH(dbc, "invalid timeout value (%lld), normalized to 0.", timeout);
timeout = 0;
}
dbc->timeout = (SQLUINTEGER)timeout;
INFOH(dbc, "timeout: %lu.", dbc->timeout);
/*
* proxy settings
*/
if (wstr2bool(&attrs->proxy_enabled)) {
ipv6 = wcsnstr(attrs->proxy_host.str, attrs->proxy_host.cnt, L':') !=
NULL;
cnt = swprintf(url.str, sizeof(buff_url)/sizeof(*buff_url),
L"" WPFWP_LDESC "://" WPFCP_DESC WPFWP_LDESC WPFCP_DESC,
LWSTR(&attrs->proxy_type),
ipv6 ? "[" : "", LWSTR(&attrs->proxy_host), ipv6 ? "]" : "");
if (cnt > 0 && attrs->proxy_port.cnt) {
n = swprintf(url.str + cnt,
sizeof(buff_url)/sizeof(*buff_url) - cnt,
L":" WPFWP_LDESC, LWSTR(&attrs->proxy_port));
} else {
n = 0;
}
if (cnt <= 0 || n < 0) {
ERRNH(dbc, "failed to print proxy URL out of type: `" LWPDL "`, "
"host: `" LWPDL "` and port: `" LWPDL "`.",
LWSTR(&attrs->proxy_type), LWSTR(&attrs->proxy_host),
LWSTR(&attrs->proxy_port));
SET_HDIAG(dbc, SQL_STATE_HY000, "printing proxy URL failed", 0);
goto err;
} else {
url.cnt = cnt + n;
}
if (! wstr_to_utf8(&url, &dbc->proxy_url)) {
ERRH(dbc, "failed to convert URL `" LWPDL "` to UTF8.",
LWSTR(&url));
SET_HDIAG(dbc, SQL_STATE_HY000, "proxy URL's UTF8 conversion "
"failed", 0);
goto err;
}
INFOH(dbc, "proxy URL: `%s`.", dbc->proxy_url.str);
if (wstr2bool(&attrs->proxy_auth_enabled)) {
if (attrs->proxy_auth_uid.cnt) {
if (! wstr_to_utf8(&attrs->proxy_auth_uid, &dbc->proxy_uid)) {
ERRH(dbc, "failed to convert proxy user ID `" LWPDL "` to"
" UTF8.", LWSTR(&attrs->proxy_auth_uid));
SET_HDIAG(dbc, SQL_STATE_HY000, "proxy UID's UTF8 "
"conversion failed", 0);
goto err;
}
INFOH(dbc, "proxy UID: `%s`.", dbc->proxy_uid.str);
if (attrs->proxy_auth_pwd.cnt) {
if (! wstr_to_utf8(&attrs->proxy_auth_pwd,
&dbc->proxy_pwd)) {
ERRH(dbc, "failed to convert proxy password [%zu] `%s`"
" to UTF8", attrs->proxy_auth_pwd.cnt,
ESODBC_PWD_VAL_SUBST);
SET_HDIAG(dbc, SQL_STATE_HY000, "proxy password's "
"UTF8 conversion failed", 0);
goto err;
}
/* indicates the presence of a non-empty password */
INFOH(dbc, "proxy PWD: " ESODBC_PWD_VAL_SUBST ".");
}
}
} else {
INFOH(dbc, "proxy authentication disabled.");
}
} else {
INFOH(dbc, "proxy disabled.");
}
/*
* set max body size
*/
if (str2bigint(&attrs->max_body_size, /*wide?*/TRUE, &max_body_size,
/*strict*/TRUE) < 0) {
ERRH(dbc, "failed to convert max body size [%zu] `" LWPDL "`.",
attrs->max_body_size.cnt, LWSTR(&attrs->max_body_size));
SET_HDIAG(dbc, SQL_STATE_HY000, "max body size setting number "
"conversion failure", 0);
goto err;
}
if ((SIZE_MAX / (1024 * 1024)) <= max_body_size || max_body_size < 0) {
ERRH(dbc, "invalid '%s' setting value (%lld).",
ESODBC_DSN_MAX_BODY_SIZE_MB, max_body_size);
SET_HDIAG(dbc, SQL_STATE_HY000, "invalid max body size setting", 0);
goto err;
} else {
dbc->amax = (size_t)max_body_size * 1024 * 1024;
if (! dbc->amax) {
WARNH(dbc, "no reply body limit set.");
}
}
INFOH(dbc, "max body size: %zu.", dbc->amax);
/*
* set max fetch size
*/
if (str2bigint(&attrs->max_fetch_size, /*wide?*/TRUE, &max_fetch_size,
/*strict*/TRUE) < 0) {
ERRH(dbc, "failed to convert max fetch size [%zu] `" LWPDL "`.",
attrs->max_fetch_size.cnt, LWSTR(&attrs->max_fetch_size));
SET_HDIAG(dbc, SQL_STATE_HY000, "max fetch size setting number "
"conversion failure", 0);
goto err;
}
if (SIZE_MAX <= max_fetch_size || max_fetch_size < 0) {
ERRH(dbc, "invalid '%s' setting value (%lld).",
ESODBC_DSN_MAX_FETCH_SIZE, max_fetch_size);
SET_HDIAG(dbc, SQL_STATE_HY000, "invalid max fetch size setting", 0);
goto err;
} else {
dbc->fetch.max = (size_t)max_fetch_size;
}
/* set the string representation of fetch_size, once for all STMTs */
if (dbc->fetch.max) {
dbc->fetch.slen = (char)attrs->max_fetch_size.cnt;
dbc->fetch.str = malloc(dbc->fetch.slen + /*\0*/1);
if (! dbc->fetch.str) {
ERRNH(dbc, "failed to alloc %cB.", dbc->fetch.slen);
RET_HDIAGS(dbc, SQL_STATE_HY001);
}
dbc->fetch.str[dbc->fetch.slen] = 0;
ascii_w2c(attrs->max_fetch_size.str, dbc->fetch.str, dbc->fetch.slen);
}
INFOH(dbc, "fetch_size: %s.", dbc->fetch.str ? dbc->fetch.str : "none" );
/*
* set the REST body format: JSON/CBOR
*/
if (EQ_CASE_WSTR(&attrs->packing, &MK_WSTR(ESODBC_DSN_PACK_JSON))) {
dbc->pack_json = TRUE;
} else if (EQ_CASE_WSTR(&attrs->packing, &MK_WSTR(ESODBC_DSN_PACK_CBOR))) {
dbc->pack_json = FALSE;
} else {
ERRH(dbc, "unknown packing encoding '" LWPDL "'.",
LWSTR(&attrs->packing));
SET_HDIAG(dbc, SQL_STATE_HY000, "invalid packing encoding setting", 0);
goto err;
}
INFOH(dbc, "pack JSON: %s.", dbc->pack_json ? "true" : "false");
/*
* set the compression option: auto/on/off
*/
if (EQ_CASE_WSTR(&attrs->compression, &MK_WSTR(ESODBC_DSN_CMPSS_AUTO))) {
dbc->compression = ESODBC_CMPSS_AUTO;
} else {
dbc->compression = wstr2bool(&attrs->compression) ?
ESODBC_CMPSS_ON : ESODBC_CMPSS_OFF;
}
INFOH(dbc, "compression: %d (" LWPDL ").", dbc->compression,
LWSTR(&attrs->compression));
/* "apply TZ" param for time conversions */
dbc->apply_tz = wstr2bool(&attrs->apply_tz);
INFOH(dbc, "apply TZ: %s.", dbc->apply_tz ? "true" : "false");
/* early execution */
dbc->early_exec = wstr2bool(&attrs->early_exec);
INFOH(dbc, "early execution: %s.", dbc->early_exec ? "true" : "false");
/* default current catalog */
if (attrs->catalog.cnt &&
(! SQL_SUCCEEDED(set_current_catalog(dbc, &attrs->catalog)))) {
goto err;
}
/* how to print the floats? */
assert(1 <= attrs->sci_floats.cnt); /* default should apply */
if ((char)attrs->sci_floats.str[0] == ESODBC_DSN_FLTS_DEF[0]) {
dbc->sci_floats = ESODBC_FLTS_DEFAULT;
} else if ((char)attrs->sci_floats.str[0] == ESODBC_DSN_FLTS_SCI[0]) {
dbc->sci_floats = ESODBC_FLTS_SCIENTIFIC;
} else if ((char)attrs->sci_floats.str[0] == ESODBC_DSN_FLTS_AUTO[0]) {
dbc->sci_floats = ESODBC_FLTS_AUTO;
} else {
ERRH(dbc, "unknown floats representation '" LWPDL "'.",
LWSTR(&attrs->sci_floats));
SET_HDIAG(dbc, SQL_STATE_HY000,
"invalid floats representation setting", 0);
goto err;
}
/* "multifield leniency" param */
dbc->mfield_lenient = wstr2bool(&attrs->mfield_lenient);
INFOH(dbc, "multifield lenient: %s.",
dbc->mfield_lenient ? "true" : "false");
/* "index include frozen" param */
dbc->idx_inc_frozen = wstr2bool(&attrs->idx_inc_frozen);
INFOH(dbc, "index include frozen: %s.",
dbc->idx_inc_frozen ? "true" : "false");
/* auto escape pattern value argument */
dbc->auto_esc_pva = wstr2bool(&attrs->auto_esc_pva);
INFOH(dbc, "auto escape PVA: %s.", dbc->auto_esc_pva ? "true" : "false");
/* varchar limit */
if (str2bigint(&attrs->varchar_limit, /*wide?*/TRUE, &varchar_limit,
/*strict*/TRUE) < 0) {
ERRH(dbc, "failed to convert varchar limit [%zu] `" LWPDL "`.",
attrs->varchar_limit.cnt, LWSTR(&attrs->varchar_limit));
SET_HDIAG(dbc, SQL_STATE_HY000, "varchar limit value conversion "
"failure", 0);
goto err;
} else if (ESODBC_MAX_KEYWORD_PRECISION < varchar_limit ||
varchar_limit < 0) {
ERRH(dbc, "varchar limit (`" LWPDL "`) outside the allowed range "
"[%d, %d].", LWSTR(&attrs->varchar_limit), 0,
ESODBC_MAX_KEYWORD_PRECISION);
SET_HDIAG(dbc, SQL_STATE_HY000, "invalid varchar limit setting", 0);
goto err;
} else {
dbc->varchar_limit = (SQLUINTEGER)varchar_limit;
/* duplicate w-char setting */
if (! (dbc->varchar_limit_str.str = calloc(attrs->varchar_limit.cnt +
/*\0*/1, sizeof(SQLWCHAR)))) {
ERRNH(dbc, "OOM: %zu w-chars.", attrs->varchar_limit.cnt + 1);
SET_HDIAG(dbc, SQL_STATE_HY001, "Memory allocation error", 0);
goto err;
}
wmemcpy(dbc->varchar_limit_str.str, attrs->varchar_limit.str,
attrs->varchar_limit.cnt);
dbc->varchar_limit_str.cnt = attrs->varchar_limit.cnt;
INFOH(dbc, "varchar limit: %lu.", dbc->varchar_limit);
}
return SQL_SUCCESS;
err:
/* release allocated resources before the failure; not the diag, tho */
cleanup_dbc(dbc);
RET_STATE(dbc->hdr.diag.state);
}