LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLConnect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 105 155 67.7 %
Date: 2024-04-26 00:35:57 Functions: 2 2 100.0 %

          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             : }

Generated by: LCOV version 1.14