Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * This code was created by Peter Harvey (mostly during Christmas 98/99).
15 : * This code is LGPL. Please ensure that this message remains in future
16 : * distributions and uses of this code (that's about all I get out of it).
17 : * - Peter Harvey pharvey@codebydesign.com
18 : *
19 : * This file has been modified for the MonetDB project. See the file
20 : * Copyright in this directory for more information.
21 : */
22 :
23 : /**********************************************************************
24 : * SQLBrowseConnect()
25 : * CLI Compliance: ODBC (Microsoft)
26 : *
27 : * Author: Martin van Dinther, Sjoerd Mullender
28 : * Date : 30 Aug 2002
29 : *
30 : **********************************************************************/
31 :
32 : #include "ODBCGlobal.h"
33 : #include "ODBCDbc.h"
34 : #include "ODBCUtil.h"
35 : #include "ODBCAttrs.h"
36 : #ifdef HAVE_STRINGS_H
37 : #include <strings.h> /* strcasecmp */
38 : #endif
39 :
40 : #ifdef HAVE_ODBCINST_H
41 : #include <odbcinst.h>
42 : #endif
43 :
44 : #ifndef HAVE_SQLGETPRIVATEPROFILESTRING
45 : #define SQLGetPrivateProfileString(section,entry,default,buffer,bufferlen,filename) ((int) strcpy_len(buffer,default,bufferlen))
46 : #endif
47 :
48 : static void
49 6 : suggest_settings(ODBCDbc *dbc, char **buf, size_t *pos, size_t *cap, char touched_as, const char *prefix)
50 : {
51 138 : for (int i = 0; i < attr_setting_count; i++) {
52 132 : const struct attr_setting *entry = &attr_settings[i];
53 132 : mparm parm = entry->parm;
54 132 : if (dbc->setting_touched[(int)parm] == touched_as) {
55 66 : const char *sep = *pos > 0 ? ";" : "";
56 66 : reallocprintf(
57 : buf, pos, cap,
58 : "%s%s%s%s%s=?",
59 66 : sep, prefix, entry->name,
60 : entry->alt_name ? ":" : "",
61 66 : entry->alt_name ? entry->alt_name : "");
62 66 : if (entry->is_enum) {
63 6 : assert(entry->values != NULL);
64 6 : *pos -= 1; // eat the '?'
65 6 : sep = "{";
66 18 : for (const char **p = entry->values; *p; p++) {
67 12 : const char *item = *p;
68 12 : reallocprintf(buf, pos, cap, "%s%s", sep, item);
69 12 : sep = ",";
70 : }
71 6 : reallocprintf(buf, pos, cap, "}");
72 : }
73 : }
74 : }
75 6 : }
76 :
77 :
78 :
79 : static SQLRETURN
80 10 : MNDBBrowseConnect(ODBCDbc *dbc,
81 : const SQLCHAR *InConnectionString,
82 : SQLSMALLINT StringLength1,
83 : SQLCHAR *OutConnectionString,
84 : SQLSMALLINT BufferLength,
85 : SQLSMALLINT *StringLength2Ptr)
86 : {
87 10 : SQLRETURN rc;
88 :
89 10 : rc = MNDBDriverConnect(
90 : dbc, NULL,
91 : InConnectionString, StringLength1,
92 : OutConnectionString, BufferLength, StringLength2Ptr,
93 : SQL_DRIVER_NOPROMPT,
94 : 0
95 : );
96 :
97 10 : if (SQL_SUCCEEDED(rc)) {
98 : return rc;
99 : }
100 :
101 : // 0 = never touched, show it
102 : // 1 = touched, do not show it
103 : // 2 = show as mandatory
104 :
105 3 : if (dbc->setting_touched[MP_USER] != 1)
106 3 : dbc->setting_touched[MP_USER] = 2;
107 3 : if (dbc->setting_touched[MP_PASSWORD] != 1)
108 3 : dbc->setting_touched[MP_PASSWORD] = 2;
109 :
110 : // Make MP_DATABASE mandatory if monetdbd asks for it.
111 6 : for (ODBCError *err = dbc->Error; err != NULL; err = getErrorRec(err, 2)) {
112 3 : if (strcmp("08001", getSqlState(err)) != 0)
113 0 : continue;
114 3 : if (strstr(getMessage(err), "monetdbd: please specify a database") == NULL)
115 3 : continue;
116 0 : dbc->setting_touched[MP_DATABASE] = 2;
117 : }
118 :
119 3 : char *buf = NULL;
120 3 : size_t pos = 0;
121 3 : size_t cap = 0;
122 3 : suggest_settings(dbc, &buf, &pos, &cap, 2, ""); // mandatory first
123 3 : suggest_settings(dbc, &buf, &pos, &cap, 0, "*"); // then optional
124 : // note that we leave out level 1, they have already been provided
125 :
126 3 : if (buf && pos) {
127 3 : size_t n = strcpy_len((char*)OutConnectionString, buf, BufferLength);
128 3 : if (StringLength2Ptr)
129 3 : *StringLength2Ptr = (SQLSMALLINT)n;
130 : }
131 :
132 3 : free(buf);
133 3 : return SQL_NEED_DATA;
134 : }
135 :
136 : SQLRETURN SQL_API
137 : SQLBrowseConnect(SQLHDBC ConnectionHandle,
138 : SQLCHAR *InConnectionString,
139 : SQLSMALLINT StringLength1,
140 : SQLCHAR *OutConnectionString,
141 : SQLSMALLINT BufferLength,
142 : SQLSMALLINT *StringLength2Ptr)
143 : {
144 5 : ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
145 :
146 : #ifdef ODBCDEBUG
147 5 : ODBCLOG("SQLBrowseConnect %p", ConnectionHandle);
148 : #endif
149 :
150 5 : if (!isValidDbc(dbc))
151 : return SQL_INVALID_HANDLE;
152 :
153 5 : clearDbcErrors(dbc);
154 :
155 5 : return MNDBBrowseConnect(dbc, InConnectionString, StringLength1, OutConnectionString, BufferLength, StringLength2Ptr);
156 : }
157 :
158 : SQLRETURN SQL_API
159 : SQLBrowseConnectA(SQLHDBC ConnectionHandle,
160 : SQLCHAR *InConnectionString,
161 : SQLSMALLINT StringLength1,
162 : SQLCHAR *OutConnectionString,
163 : SQLSMALLINT BufferLength,
164 : SQLSMALLINT *StringLength2Ptr)
165 : {
166 0 : return SQLBrowseConnect(ConnectionHandle, InConnectionString, StringLength1, OutConnectionString, BufferLength, StringLength2Ptr);
167 : }
168 :
169 : SQLRETURN SQL_API
170 : SQLBrowseConnectW(SQLHDBC ConnectionHandle,
171 : SQLWCHAR *InConnectionString,
172 : SQLSMALLINT StringLength1,
173 : SQLWCHAR *OutConnectionString,
174 : SQLSMALLINT BufferLength,
175 : SQLSMALLINT *StringLength2Ptr)
176 : {
177 5 : ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
178 5 : SQLCHAR *in = NULL, *out;
179 5 : SQLSMALLINT n;
180 5 : SQLRETURN rc;
181 :
182 : #ifdef ODBCDEBUG
183 5 : ODBCLOG("SQLBrowseConnectW %p", ConnectionHandle);
184 : #endif
185 :
186 5 : if (!isValidDbc(dbc))
187 : return SQL_INVALID_HANDLE;
188 :
189 5 : clearDbcErrors(dbc);
190 :
191 5 : fixWcharIn(InConnectionString, StringLength1, SQLCHAR, in,
192 : addDbcError, dbc, return SQL_ERROR);
193 5 : out = malloc(2048);
194 5 : if (out == NULL) {
195 : /* Memory allocation error */
196 0 : addDbcError(dbc, "HY001", NULL, 0);
197 0 : return SQL_ERROR;
198 : }
199 5 : rc = MNDBBrowseConnect(dbc, in, SQL_NTS, out, 2048, &n);
200 5 : if (SQL_SUCCEEDED(rc) || rc == SQL_NEED_DATA) {
201 5 : fixWcharOut(rc, out, n, OutConnectionString, BufferLength,
202 : StringLength2Ptr, 1, addDbcError, dbc);
203 : }
204 5 : free(out);
205 5 : if (in)
206 5 : free(in);
207 : return rc;
208 : }
|