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 (thats 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 : * SQLConnect()
25 : * CLI Compliance: ISO 92
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 <time.h>
36 :
37 : #ifdef HAVE_ODBCINST_H
38 : #include <odbcinst.h>
39 : #endif
40 :
41 : #ifndef HAVE_SQLGETPRIVATEPROFILESTRING
42 : #define SQLGetPrivateProfileString(section,entry,default,buffer,bufferlen,filename) ((int) strcpy_len(buffer,default,bufferlen))
43 : #endif
44 :
45 : static void
46 6 : get_serverinfo(ODBCDbc *dbc)
47 : {
48 6 : MapiHdl hdl;
49 6 : char *n, *v;
50 :
51 6 : if ((hdl = mapi_query(dbc->mid, "select name, value from sys.env() where name in ('monet_version', 'gdk_dbname', 'max_clients', 'raw_strings')")) == NULL)
52 : return;
53 6 : dbc->raw_strings = false;
54 30 : while (mapi_fetch_row(hdl)) {
55 24 : n = mapi_fetch_field(hdl, 0);
56 24 : v = mapi_fetch_field(hdl, 1);
57 24 : if (strcmp(n, "monet_version") == 0) {
58 6 : sscanf(v, "%hd.%hd.%hd",
59 : &dbc->major, &dbc->minor, &dbc->patch);
60 : } else
61 18 : if (strcmp(n, "max_clients") == 0) {
62 6 : sscanf(v, "%hu", &dbc->maxclients);
63 12 : } else if (strcmp(n, "raw_strings") == 0) {
64 6 : dbc->raw_strings = strcmp(v, "true") == 0;
65 : } else {
66 6 : assert(strcmp(n, "gdk_dbname") == 0);
67 6 : assert(dbc->dbname == NULL ||
68 : strcmp(dbc->dbname, v) == 0);
69 6 : if (dbc->dbname)
70 6 : free(dbc->dbname);
71 6 : dbc->dbname = strdup(v);
72 : }
73 : }
74 6 : mapi_close_handle(hdl);
75 6 : if ((hdl = mapi_query(dbc->mid, "select id from sys._tables where name = 'comments' and schema_id = (select id from sys.schemas where name = 'sys')")) == NULL)
76 : return;
77 : n = NULL;
78 12 : while (mapi_fetch_row(hdl)) {
79 6 : n = mapi_fetch_field(hdl, 0);
80 : }
81 6 : dbc->has_comment = n != NULL;
82 6 : mapi_close_handle(hdl);
83 : }
84 :
85 : SQLRETURN
86 6 : MNDBConnect(ODBCDbc *dbc,
87 : const SQLCHAR *ServerName,
88 : SQLSMALLINT NameLength1,
89 : const SQLCHAR *UserName,
90 : SQLSMALLINT NameLength2,
91 : const SQLCHAR *Authentication,
92 : SQLSMALLINT NameLength3,
93 : const char *host,
94 : int port,
95 : const char *dbname,
96 : int mapToLongVarchar)
97 : {
98 6 : SQLRETURN rc = SQL_SUCCESS;
99 6 : char *dsn = NULL;
100 6 : char uid[32];
101 6 : char pwd[32];
102 6 : char buf[256];
103 6 : char db[32];
104 6 : int n;
105 6 : Mapi mid;
106 :
107 : /* check connection state, should not be connected */
108 6 : if (dbc->Connected) {
109 : /* Connection name in use */
110 0 : addDbcError(dbc, "08002", NULL, 0);
111 0 : return SQL_ERROR;
112 : }
113 :
114 : /* convert input string parameters to normal null terminated C strings */
115 6 : fixODBCstring(ServerName, NameLength1, SQLSMALLINT,
116 : addDbcError, dbc, return SQL_ERROR);
117 6 : if (NameLength1 > 0) {
118 6 : dsn = dupODBCstring(ServerName, (size_t) NameLength1);
119 6 : if (dsn == NULL) {
120 : /* Memory allocation error */
121 0 : addDbcError(dbc, "HY001", NULL, 0);
122 0 : return SQL_ERROR;
123 : }
124 : }
125 :
126 : #ifdef ODBCDEBUG
127 6 : if ((ODBCdebug == NULL || *ODBCdebug == 0) && dsn && *dsn) {
128 6 : char logfile[2048];
129 6 : n = SQLGetPrivateProfileString(dsn, "logfile", "",
130 : logfile, sizeof(logfile),
131 : "odbc.ini");
132 6 : if (n > 0) {
133 0 : free((void *) ODBCdebug); /* discard const */
134 : #ifdef NATIVE_WIN32
135 : size_t attrlen = strlen(logfile);
136 : SQLWCHAR *wattr = malloc((attrlen + 1) * sizeof(SQLWCHAR));
137 : if (ODBCutf82wchar(logfile,
138 : (SQLINTEGER) attrlen,
139 : wattr,
140 : (SQLLEN) ((attrlen + 1) * sizeof(SQLWCHAR)),
141 : NULL,
142 : NULL)) {
143 : free(wattr);
144 : wattr = NULL;
145 : }
146 : ODBCdebug = wattr;
147 : #else
148 0 : ODBCdebug = strdup(logfile);
149 : #endif
150 : }
151 : }
152 : #endif
153 :
154 6 : if (dsn && *dsn)
155 6 : n = SQLGetPrivateProfileString(dsn, "uid", "monetdb",
156 : uid, sizeof(uid), "odbc.ini");
157 : else
158 : n = 0;
159 6 : fixODBCstring(UserName, NameLength2, SQLSMALLINT,
160 : addDbcError, dbc, if (dsn) free(dsn); return SQL_ERROR);
161 6 : if (n == 0 && NameLength2 == 0) {
162 0 : if (dsn)
163 0 : free(dsn);
164 : /* Invalid authorization specification */
165 0 : addDbcError(dbc, "28000", NULL, 0);
166 0 : return SQL_ERROR;
167 : }
168 6 : if (NameLength2 > 0) {
169 5 : if ((size_t)NameLength2 >= sizeof(uid))
170 0 : NameLength2 = sizeof(uid) - 1;
171 5 : strncpy(uid, (char *) UserName, NameLength2);
172 5 : uid[NameLength2] = 0;
173 : }
174 6 : if (dsn && *dsn)
175 6 : n = SQLGetPrivateProfileString(dsn, "pwd", "monetdb",
176 : pwd, sizeof(pwd), "odbc.ini");
177 : else
178 : n = 0;
179 6 : fixODBCstring(Authentication, NameLength3, SQLSMALLINT,
180 : addDbcError, dbc, if (dsn) free(dsn); return SQL_ERROR);
181 6 : if (n == 0 && NameLength3 == 0) {
182 0 : if (dsn)
183 0 : free(dsn);
184 : /* Invalid authorization specification */
185 0 : addDbcError(dbc, "28000", NULL, 0);
186 0 : return SQL_ERROR;
187 : }
188 6 : if (NameLength3 > 0) {
189 5 : if ((size_t)NameLength3 >= sizeof(pwd))
190 0 : NameLength3 = sizeof(pwd) - 1;
191 5 : strncpy(pwd, (char *) Authentication, NameLength3);
192 5 : pwd[NameLength3] = 0;
193 : }
194 :
195 6 : if (dbname == NULL || *dbname == 0) {
196 6 : dbname = dbc->dbname;
197 : }
198 6 : if (dbname == NULL || *dbname == 0) {
199 6 : if (dsn && *dsn) {
200 6 : n = SQLGetPrivateProfileString(dsn, "database", "", db,
201 : sizeof(db), "odbc.ini");
202 6 : if (n > 0)
203 : dbname = db;
204 : }
205 : }
206 6 : if (dbname && !*dbname)
207 0 : dbname = NULL;
208 :
209 : #ifdef NATIVE_WIN32
210 : wchar_t *s;
211 : if (port == 0 && (s = _wgetenv(L"MAPIPORT")) != NULL)
212 : port = _wtoi(s);
213 : #else
214 6 : char *s;
215 6 : if (port == 0 && (s = getenv("MAPIPORT")) != NULL)
216 6 : port = atoi(s);
217 : #endif
218 6 : if (port == 0 && dsn && *dsn) {
219 0 : n = SQLGetPrivateProfileString(dsn, "port", MAPI_PORT_STR,
220 : buf, sizeof(buf), "odbc.ini");
221 0 : if (n > 0)
222 0 : port = atoi(buf);
223 : }
224 6 : if (port == 0)
225 0 : port = MAPI_PORT;
226 :
227 6 : if (host == NULL || *host == 0) {
228 6 : host = "localhost";
229 6 : if (dsn && *dsn) {
230 6 : n = SQLGetPrivateProfileString(dsn, "host", "localhost",
231 : buf, sizeof(buf),
232 : "odbc.ini");
233 6 : if (n > 0)
234 6 : host = buf;
235 : }
236 : }
237 :
238 : #ifdef ODBCDEBUG
239 6 : ODBCLOG("SQLConnect: DSN=%s UID=%s PWD=%s host=%s port=%d database=%s\n",
240 : dsn ? dsn : "(null)", uid, pwd, host, port,
241 : dbname ? dbname : "(null)");
242 : #endif
243 :
244 : /* connect to a server on host via port */
245 : /* FIXME: use dbname from ODBC connect string/options here */
246 6 : mid = mapi_mapi(host, port, uid, pwd, "sql", dbname);
247 6 : if (mid) {
248 6 : mapi_setAutocommit(mid, dbc->sql_attr_autocommit == SQL_AUTOCOMMIT_ON);
249 6 : mapi_set_size_header(mid, true);
250 6 : mapi_reconnect(mid);
251 : }
252 6 : if (mid == NULL || mapi_error(mid)) {
253 : /* Client unable to establish connection */
254 0 : addDbcError(dbc, "08001", mid ? mapi_error_str(mid) : NULL, 0);
255 0 : rc = SQL_ERROR;
256 : /* clean up */
257 0 : if (mid)
258 0 : mapi_destroy(mid);
259 0 : if (dsn != NULL)
260 0 : free(dsn);
261 : } else {
262 : /* store internal information and clean up buffers */
263 6 : dbc->Connected = true;
264 6 : dbc->mid = mid;
265 6 : if (dbc->dsn != NULL)
266 0 : free(dbc->dsn);
267 6 : dbc->dsn = dsn;
268 6 : if (dbc->uid != NULL)
269 0 : free(dbc->uid);
270 6 : dbc->uid = strdup(uid);
271 6 : if (dbc->pwd != NULL)
272 0 : free(dbc->pwd);
273 6 : dbc->pwd = strdup(pwd);
274 6 : if (dbc->host)
275 0 : free(dbc->host);
276 6 : dbc->host = strdup(host);
277 6 : if (dbname) /* dup before dbname is freed */
278 6 : dbname = strdup(dbname);
279 6 : if (dbc->dbname != NULL)
280 0 : free(dbc->dbname);
281 6 : dbc->dbname = (char *) dbname; /* discard const */
282 6 : dbc->mapToLongVarchar = mapToLongVarchar;
283 6 : get_serverinfo(dbc);
284 : /* set timeout after we're connected */
285 6 : mapi_timeout(mid, dbc->sql_attr_connection_timeout * 1000);
286 : }
287 :
288 : return rc;
289 : }
290 :
291 : SQLRETURN SQL_API
292 : SQLConnect(SQLHDBC ConnectionHandle,
293 : SQLCHAR *ServerName,
294 : SQLSMALLINT NameLength1,
295 : SQLCHAR *UserName,
296 : SQLSMALLINT NameLength2,
297 : SQLCHAR *Authentication,
298 : SQLSMALLINT NameLength3)
299 : {
300 : #ifdef ODBCDEBUG
301 5 : ODBCLOG("SQLConnect %p\n", ConnectionHandle);
302 : #endif
303 :
304 5 : if (!isValidDbc((ODBCDbc *) ConnectionHandle))
305 : return SQL_INVALID_HANDLE;
306 :
307 5 : clearDbcErrors((ODBCDbc *) ConnectionHandle);
308 :
309 5 : return MNDBConnect((ODBCDbc *) ConnectionHandle,
310 : ServerName, NameLength1,
311 : UserName, NameLength2,
312 : Authentication, NameLength3,
313 : NULL, 0, NULL, 0);
314 : }
315 :
316 : SQLRETURN SQL_API
317 : SQLConnectA(SQLHDBC ConnectionHandle,
318 : SQLCHAR *ServerName,
319 : SQLSMALLINT NameLength1,
320 : SQLCHAR *UserName,
321 : SQLSMALLINT NameLength2,
322 : SQLCHAR *Authentication,
323 : SQLSMALLINT NameLength3)
324 : {
325 0 : return SQLConnect(ConnectionHandle,
326 : ServerName, NameLength1,
327 : UserName, NameLength2,
328 : Authentication, NameLength3);
329 : }
330 :
331 : SQLRETURN SQL_API
332 : SQLConnectW(SQLHDBC ConnectionHandle,
333 : SQLWCHAR *ServerName,
334 : SQLSMALLINT NameLength1,
335 : SQLWCHAR *UserName,
336 : SQLSMALLINT NameLength2,
337 : SQLWCHAR *Authentication,
338 : SQLSMALLINT NameLength3)
339 : {
340 0 : SQLCHAR *ds = NULL, *uid = NULL, *pwd = NULL;
341 0 : SQLRETURN rc = SQL_ERROR;
342 0 : ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
343 :
344 : #ifdef ODBCDEBUG
345 0 : ODBCLOG("SQLConnectW %p\n", ConnectionHandle);
346 : #endif
347 :
348 0 : if (!isValidDbc(dbc))
349 : return SQL_INVALID_HANDLE;
350 :
351 0 : clearDbcErrors(dbc);
352 :
353 0 : fixWcharIn(ServerName, NameLength1, SQLCHAR, ds,
354 : addDbcError, dbc, goto bailout);
355 0 : fixWcharIn(UserName, NameLength2, SQLCHAR, uid,
356 : addDbcError, dbc, goto bailout);
357 0 : fixWcharIn(Authentication, NameLength3, SQLCHAR, pwd,
358 : addDbcError, dbc, goto bailout);
359 :
360 0 : rc = MNDBConnect(dbc,
361 : ds, SQL_NTS,
362 : uid, SQL_NTS,
363 : pwd, SQL_NTS,
364 : NULL, 0, NULL, 0);
365 :
366 0 : bailout:
367 0 : if (ds)
368 0 : free(ds);
369 0 : if (uid)
370 0 : free(uid);
371 0 : if (pwd)
372 0 : free(pwd);
373 : return rc;
374 : }
|