LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLDriverConnect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 110 139 79.1 %
Date: 2024-10-03 20:03:20 Functions: 3 3 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 (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             :  * SQLDriverConnect()
      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>              /* for strcasecmp */
      38             : #else
      39             : #include <string.h>
      40             : #endif
      41             : 
      42             : int
      43         148 : ODBCGetKeyAttr(const SQLCHAR **conn, SQLSMALLINT *nconn, char **key, char **attr)
      44             : {
      45         148 :         const SQLCHAR *p;
      46         148 :         size_t len;
      47             : 
      48         148 :         *key = *attr = NULL;
      49             : 
      50         148 :         p = *conn;
      51         148 :         if (!**conn)
      52             :                 return 0;
      53         680 :         while (*nconn > 0 && **conn && **conn != '=' && **conn != ';') {
      54         568 :                 (*conn)++;
      55         568 :                 (*nconn)--;
      56             :         }
      57         112 :         if (*nconn == 0 || !**conn || **conn == ';')
      58             :                 return 0;
      59         111 :         len = *conn - p;
      60         111 :         *key = (char *) malloc(len + 1);
      61         111 :         if (*key == NULL)
      62             :                 return -1;
      63         111 :         strcpy_len(*key, (char *) p, len + 1);
      64         111 :         (*conn)++;
      65         111 :         (*nconn)--;
      66         111 :         p = *conn;
      67             : 
      68         111 :         if (*nconn > 0 && **conn == '{' && strcasecmp(*key, "DRIVER") == 0) {
      69          10 :                 (*conn)++;
      70          10 :                 (*nconn)--;
      71          10 :                 p++;
      72          80 :                 while (*nconn > 0 && **conn && **conn != '}') {
      73          70 :                         (*conn)++;
      74          70 :                         (*nconn)--;
      75             :                 }
      76          10 :                 len = *conn - p;
      77          10 :                 *attr = (char *) malloc(len + 1);
      78          10 :                 if (*attr == NULL) {
      79           0 :                         free(*key);
      80           0 :                         *key = NULL;
      81           0 :                         return -1;
      82             :                 }
      83          10 :                 strcpy_len(*attr, (char *) p, len + 1);
      84          10 :                 (*conn)++;
      85          10 :                 (*nconn)--;
      86             :                 /* should check that *nconn == 0 || **conn == ';' */
      87             :         } else {
      88        1247 :                 while (*nconn > 0 && **conn && **conn != ';') {
      89        1146 :                         (*conn)++;
      90        1146 :                         (*nconn)--;
      91             :                 }
      92         101 :                 len = *conn - p;
      93         101 :                 *attr = (char *) malloc(len + 1);
      94         101 :                 if (*attr == NULL) {
      95           0 :                         free(*key);
      96           0 :                         *key = NULL;
      97           0 :                         return -1;
      98             :                 }
      99         101 :                 strcpy_len(*attr, (char *) p, len + 1);
     100             :         }
     101         111 :         if (*nconn > 0 && **conn) {
     102          79 :                 (*conn)++;
     103          79 :                 (*nconn)--;
     104             :         }
     105             :         return 1;
     106             : }
     107             : 
     108             : #ifdef ODBCDEBUG
     109             : static char *
     110          29 : translateDriverCompletion(SQLUSMALLINT DriverCompletion)
     111             : {
     112          29 :         switch (DriverCompletion) {
     113             :         case SQL_DRIVER_PROMPT:
     114             :                 return "SQL_DRIVER_PROMPT";
     115           0 :         case SQL_DRIVER_COMPLETE:
     116           0 :                 return "SQL_DRIVER_COMPLETE";
     117           0 :         case SQL_DRIVER_COMPLETE_REQUIRED:
     118           0 :                 return "SQL_DRIVER_COMPLETE_REQUIRED";
     119          29 :         case SQL_DRIVER_NOPROMPT:
     120          29 :                 return "SQL_DRIVER_NOPROMPT";
     121           0 :         default:
     122           0 :                 return "unknown";
     123             :         }
     124             : }
     125             : #endif
     126             : 
     127             : SQLRETURN
     128          29 : MNDBDriverConnect(ODBCDbc *dbc,
     129             :                   SQLHWND WindowHandle,
     130             :                   const SQLCHAR *InConnectionString,
     131             :                   SQLSMALLINT StringLength1,
     132             :                   SQLCHAR *OutConnectionString,
     133             :                   SQLSMALLINT BufferLength,
     134             :                   SQLSMALLINT *StringLength2Ptr,
     135             :                   SQLUSMALLINT DriverCompletion,
     136             :                   int tryOnly)
     137             : {
     138          29 :         (void) WindowHandle;
     139             : 
     140          29 :         SQLRETURN rc = SQL_SUCCESS;
     141          29 :         const char *sqlstate = NULL;
     142          29 :         size_t out_len;
     143          29 :         const char *scratch_no_alloc;
     144             : 
     145             :         // These will be free'd at the end label
     146          29 :         msettings *settings = NULL;
     147          29 :         char *scratch_alloc = NULL;
     148          29 :         char *dsn = NULL;
     149             : 
     150             :         /* check connection state, should not be connected */
     151          29 :         if (dbc->Connected) {
     152           0 :                 sqlstate = "08002";
     153           0 :                 goto failure;
     154             :         }
     155             : 
     156          29 :         fixODBCstring(InConnectionString, StringLength1, SQLSMALLINT,
     157             :                       addDbcError, dbc, return SQL_ERROR);
     158             : 
     159          29 :         settings = msettings_clone(dbc->settings);
     160          29 :         if (!settings)
     161           0 :                 goto failure;
     162             : 
     163             : #ifdef ODBCDEBUG
     164          29 :         ODBCLOG("\"%.*s\" %s\n", StringLength1,
     165             :                 (char *) InConnectionString,
     166             :                 translateDriverCompletion(DriverCompletion));
     167             : #endif
     168             : 
     169             :         /* check input arguments */
     170          29 :         switch (DriverCompletion) {
     171             :         case SQL_DRIVER_PROMPT:
     172             :         case SQL_DRIVER_COMPLETE:
     173             :         case SQL_DRIVER_COMPLETE_REQUIRED:
     174             :         case SQL_DRIVER_NOPROMPT:
     175          29 :                 break;
     176           0 :         default:
     177             :                 /* Invalid attribute/option identifier */
     178           0 :                 sqlstate = "HY092";
     179           0 :                 goto failure;
     180             :         }
     181             : 
     182          29 :         rc = takeFromConnString(dbc, settings, InConnectionString, StringLength1, &dsn);
     183          29 :         if (!SQL_SUCCEEDED(rc))
     184           0 :                 goto end;
     185             : 
     186          29 :         if (!msettings_validate(settings, &scratch_alloc)) {
     187           0 :                 addDbcError(dbc, "HY009", scratch_alloc, 0);
     188           0 :                 rc = SQL_ERROR;
     189           0 :                 goto end;
     190             :         }
     191             : 
     192             :         // Build a connect string for the current connection and put it in the out buffer.
     193          50 :         scratch_alloc = buildConnectionString(dsn ? dsn : "DEFAULT", settings);
     194          29 :         if (!scratch_alloc)
     195           0 :                 goto failure;
     196          29 :         out_len = strcpy_len((char*)OutConnectionString, scratch_alloc, BufferLength);
     197          29 :         if (StringLength2Ptr)
     198          29 :                 *StringLength2Ptr = (SQLSMALLINT)out_len;
     199          29 :         if (out_len + 1 > (size_t)BufferLength) {
     200           3 :                 addDbcError(dbc, "01004", NULL, 0);
     201           3 :                 rc = SQL_SUCCESS_WITH_INFO;
     202             :         }
     203             : 
     204          29 :         if (tryOnly) {
     205           3 :                 assert(sqlstate == NULL);
     206           3 :                 goto end;
     207             :         }
     208             : 
     209          26 :         scratch_no_alloc = msetting_string(settings, MP_LOGFILE);
     210          26 :         if (*scratch_no_alloc)
     211           0 :                 setODBCdebug(scratch_no_alloc, false);
     212             : 
     213          26 :         rc = MNDBConnectSettings(dbc, dsn, settings);
     214          26 :         settings = NULL; // do not free now
     215             : 
     216             :         // always go to end, MNDBConnectSettings has already logged any failures
     217          26 :         goto end;
     218             : 
     219             : failure:
     220           0 :         if (sqlstate == NULL)
     221             :                 sqlstate = "HY001"; // malloc failure
     222             :         rc = SQL_ERROR;
     223             :         // fallthrough
     224          29 : end:
     225          29 :         if (sqlstate != NULL)
     226           0 :                 addDbcError(dbc, sqlstate, NULL, 0);
     227          29 :         msettings_destroy(settings);
     228          29 :         free(scratch_alloc);
     229          29 :         free(dsn);
     230          29 :         return rc;
     231             : }
     232             : 
     233             : SQLRETURN SQL_API
     234             : SQLDriverConnect(SQLHDBC ConnectionHandle,
     235             :                  SQLHWND WindowHandle,
     236             :                  SQLCHAR *InConnectionString,
     237             :                  SQLSMALLINT StringLength1,
     238             :                  SQLCHAR *OutConnectionString,
     239             :                  SQLSMALLINT BufferLength,
     240             :                  SQLSMALLINT *StringLength2Ptr,
     241             :                  SQLUSMALLINT DriverCompletion)
     242             : {
     243          13 :         ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
     244             : 
     245             : #ifdef ODBCDEBUG
     246          13 :         ODBCLOG("SQLDriverConnect %p ", ConnectionHandle);
     247             : #endif
     248             : 
     249          13 :         if (!isValidDbc(dbc))
     250             :                 return SQL_INVALID_HANDLE;
     251             : 
     252          13 :         clearDbcErrors(dbc);
     253             : 
     254          13 :         return MNDBDriverConnect(dbc,
     255             :                                  WindowHandle,
     256             :                                  InConnectionString,
     257             :                                  StringLength1,
     258             :                                  OutConnectionString,
     259             :                                  BufferLength,
     260             :                                  StringLength2Ptr,
     261             :                                  DriverCompletion,
     262             :                                  0);
     263             : }
     264             : 
     265             : SQLRETURN SQL_API
     266             : SQLDriverConnectA(SQLHDBC ConnectionHandle,
     267             :                   SQLHWND WindowHandle,
     268             :                   SQLCHAR *InConnectionString,
     269             :                   SQLSMALLINT StringLength1,
     270             :                   SQLCHAR *OutConnectionString,
     271             :                   SQLSMALLINT BufferLength,
     272             :                   SQLSMALLINT *StringLength2Ptr,
     273             :                   SQLUSMALLINT DriverCompletion)
     274             : {
     275           0 :         return SQLDriverConnect(ConnectionHandle,
     276             :                                 WindowHandle,
     277             :                                 InConnectionString,
     278             :                                 StringLength1,
     279             :                                 OutConnectionString,
     280             :                                 BufferLength,
     281             :                                 StringLength2Ptr,
     282             :                                 DriverCompletion);
     283             : }
     284             : 
     285             : SQLRETURN SQL_API
     286             : SQLDriverConnectW(SQLHDBC ConnectionHandle,
     287             :                   SQLHWND WindowHandle,
     288             :                   SQLWCHAR *InConnectionString,
     289             :                   SQLSMALLINT StringLength1,
     290             :                   SQLWCHAR *OutConnectionString,
     291             :                   SQLSMALLINT BufferLength,
     292             :                   SQLSMALLINT *StringLength2Ptr,
     293             :                   SQLUSMALLINT DriverCompletion)
     294             : {
     295           3 :         ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
     296           3 :         SQLCHAR *in = NULL, *out;
     297           3 :         SQLSMALLINT n;
     298           3 :         SQLRETURN rc;
     299             : 
     300             : #ifdef ODBCDEBUG
     301           3 :         ODBCLOG("SQLDriverConnectW %p ", ConnectionHandle);
     302             : #endif
     303             : 
     304           3 :         if (!isValidDbc(dbc))
     305             :                 return SQL_INVALID_HANDLE;
     306             : 
     307           3 :         clearDbcErrors(dbc);
     308             : 
     309           3 :         fixWcharIn(InConnectionString, StringLength1, SQLCHAR, in,
     310             :                    addDbcError, dbc, return SQL_ERROR);
     311             : 
     312           3 :         rc = MNDBDriverConnect(dbc, WindowHandle, in, SQL_NTS, NULL, 0, &n,
     313             :                                DriverCompletion, 1);  // 1 = Try Only
     314           3 :         if (!SQL_SUCCEEDED(rc))
     315             :                 return rc;
     316           3 :         clearDbcErrors(dbc);
     317           3 :         n++;                    /* account for NUL byte */
     318           3 :         out = malloc(n);
     319           3 :         if (out == NULL) {
     320             :                 /* Memory allocation error */
     321           0 :                 addDbcError(dbc, "HY001", NULL, 0);
     322           0 :                 return SQL_ERROR;
     323             :         }
     324           3 :         rc = MNDBDriverConnect(dbc, WindowHandle, in, SQL_NTS, out, n, &n,
     325             :                                DriverCompletion, 0);
     326           3 :         if (SQL_SUCCEEDED(rc)) {
     327           2 :                 fixWcharOut(rc, out, n, OutConnectionString, BufferLength,
     328             :                             StringLength2Ptr, 1, addDbcError, dbc);
     329             :         }
     330           3 :         free(out);
     331           3 :         if (in)
     332           3 :                 free(in);
     333             :         return rc;
     334             : }

Generated by: LCOV version 1.14