tdbc::odbc

Check-in [a233639b90]
Login
Bounty program for improvements to Tcl and certain Tcl packages.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Make tdbcodbc work with C++ compiler.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a233639b905861186dc096fd3be8adbbbd3650459dc2bb5ff4c30f45da444408
User & Date: jan.nijtmans 2019-08-30 14:52:23
Context
2019-10-04
17:12
Bump to version 1.1.1. for release. check-in: 357766791a user: dgp tags: trunk
2019-09-13
16:27
Fix for a typo in defining the SQLLEN and SQLULEN data types on Win64. (__WIN64 should be just _WIN64.) Closed-Leaf check-in: 0837f4e778 user: kbk tags: bug-647ec7268f
2019-08-30
14:52
Make tdbcodbc work with C++ compiler. check-in: a233639b90 user: jan.nijtmans tags: trunk
2019-08-29
11:08
Updated to latest Tcl nmake files. Bug fix [d6c4db25560b1a8c3a26f9369e57cf00327cb9b4]. check-in: c98b08b629 user: apnadkarni tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to configure.

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
...
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
....
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
....
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
....
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
....
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
....
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
................................................................................
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
................................................................................
  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
    psdir=$ac_optarg ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -runstatedir | --runstatedir | --runstatedi | --runstated \
  | --runstate | --runstat | --runsta | --runst | --runs \
  | --run | --ru | --r)
    ac_prev=runstatedir ;;
  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
  | --run=* | --ru=* | --r=*)
    runstatedir=$ac_optarg ;;

  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir=$ac_optarg ;;

  -sharedstatedir | --sharedstatedir | --sharedstatedi \
................................................................................
  esac
fi

# Check all directory arguments for consistency.
for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
		datadir sysconfdir sharedstatedir localstatedir includedir \
		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
		libdir localedir mandir runstatedir
do
  eval ac_val=\$$ac_var
  # Remove trailing slashes.
  case $ac_val in
    */ )
      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
      eval $ac_var=\$ac_val;;
................................................................................
Fine tuning of the installation directories:
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
................................................................................
    # If the user did not set CFLAGS, set it now to keep macros
    # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
    if test "${CFLAGS+set}" != "set" ; then
	CFLAGS=""
    fi

    case "`uname -s`" in
	*win32*|*WIN32*|*MINGW32_*|*MINGW64_*)
	    # Extract the first word of "cygpath", so it can be a program name with args.
set dummy cygpath; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CYGPATH+:} false; then :
  $as_echo_n "(cached) " >&6
else
................................................................................
    # standard manufacturer compiler.

    if test "$GCC" = yes; then :

	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*|MINGW64_*) ;;
	    IRIX*) ;;
	    NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    windows) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac






<







 







<







 







<
<
<
<
<
<
<
<
<







 







|







 







<







 







|







 







|







718
719
720
721
722
723
724

725
726
727
728
729
730
731
...
798
799
800
801
802
803
804

805
806
807
808
809
810
811
....
1050
1051
1052
1053
1054
1055
1056









1057
1058
1059
1060
1061
1062
1063
....
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
....
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
....
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
....
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir

localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
................................................................................
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'

includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
................................................................................
  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
    psdir=$ac_optarg ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;










  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir=$ac_optarg ;;

  -sharedstatedir | --sharedstatedir | --sharedstatedi \
................................................................................
  esac
fi

# Check all directory arguments for consistency.
for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
		datadir sysconfdir sharedstatedir localstatedir includedir \
		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
		libdir localedir mandir
do
  eval ac_val=\$$ac_var
  # Remove trailing slashes.
  case $ac_val in
    */ )
      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
      eval $ac_var=\$ac_val;;
................................................................................
Fine tuning of the installation directories:
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]

  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
................................................................................
    # If the user did not set CFLAGS, set it now to keep macros
    # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
    if test "${CFLAGS+set}" != "set" ; then
	CFLAGS=""
    fi

    case "`uname -s`" in
	*win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*)
	    # Extract the first word of "cygpath", so it can be a program name with args.
set dummy cygpath; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CYGPATH+:} false; then :
  $as_echo_n "(cached) " >&6
else
................................................................................
    # standard manufacturer compiler.

    if test "$GCC" = yes; then :

	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;;
	    IRIX*) ;;
	    NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    windows) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac

Changes to configure.ac.

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# This also calls AC_PROG_CC and a few others to create the basic setup
# necessary to compile executables.
#-----------------------------------------------------------------------

TEA_SETUP_COMPILER

#-----------------------------------------------------------------------
# Setup inlining if available. Check sizeof long long. 
#-----------------------------------------------------------------------

AC_C_INLINE
AC_CHECK_TYPE([long long],[
    AC_DEFINE([HAVE_LONG_LONG],[1])
    AC_CHECK_SIZEOF([long long])
],[],[])






|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# This also calls AC_PROG_CC and a few others to create the basic setup
# necessary to compile executables.
#-----------------------------------------------------------------------

TEA_SETUP_COMPILER

#-----------------------------------------------------------------------
# Setup inlining if available. Check sizeof long long.
#-----------------------------------------------------------------------

AC_C_INLINE
AC_CHECK_TYPE([long long],[
    AC_DEFINE([HAVE_LONG_LONG],[1])
    AC_CHECK_SIZEOF([long long])
],[],[])

Changes to generic/tdbcodbc.c.

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
....
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
....
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
....
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
....
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
....
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
....
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298

5299
5300
5301
5302
5303
5304
5305
....
5326
5327
5328
5329
5330
5331
5332



5333
5334
5335
5336
5337
5338
5339
5340
....
5598
5599
5600
5601
5602
5603
5604



5605
5606
5607
5608
5609
5610
5611
static Tcl_LoadHandle odbcLoadHandle = NULL;
				/* Handle to the ODBC client library */
static Tcl_LoadHandle odbcInstLoadHandle = NULL;
				/* Handle to the ODBC installer library */
static SQLHENV hEnv = SQL_NULL_HENV;
				/* Handle to the global ODBC environment */
static int hEnvRefCount = 0;	/* Reference count on the global environment */
static int sizeofSQLWCHAR = sizeof(SQLWCHAR);
				/* Preset, will be autodetected later */

/*
 * Objects to create within the literal pool
 */

const char* const LiteralValues[] = {
................................................................................

/*
 * Structure for looking up a string that maps to an ODBC constant
 */

typedef struct OdbcConstant {
    const char* name;		/* Constant name */
    SQLSMALLINT value;		/* Constant value */
} OdbcConstant;

/*
 * Constants for the directions of parameter transmission
 */

const static OdbcConstant OdbcParamDirections[] = {
................................................................................
		    static const char BE16sig[] = {
			'\0', '#', '\0', '#'
		    };
		    static const char LE16sig[] = {
			'#', '\0', '#', '\0'
		    };

		    if (infoLen > sizeof(info)) {
			infoLen = sizeof(info);
		    }
		    for (i = 0; i < infoLen; i++) {
			if (info[i] >= '0' && info[i] <= '9') {
			    info[i] = '#';
			}
		    }
................................................................................
				/* Name of the current column */
    Tcl_DString colNameDS;	/* Name of the current column, translated */
    Tcl_Obj* colNameObj;	/* Name of the current column, packaged in
				 * a Tcl_Obj */
    Tcl_HashTable nameHash;	/* Hash table to manage column name
				 * uniqueness. */
    Tcl_HashEntry* nameEntry;	/* Hash table entry for the current name */
    int new;			/* Flag that column name is unique */
    int count;			/* Count to append to the name */
    char numbuf[16];		/* Buffer to hold the appended count */
    SQLSMALLINT i;
    int retry;
    int status = TCL_ERROR;

    /* Create a hash table to manage column name uniqueness */

    Tcl_InitHashTable(&nameHash, TCL_STRING_KEYS);
    nameEntry = Tcl_CreateHashEntry(&nameHash, "", &new);
    Tcl_SetHashValue(nameEntry, (ClientData) 0);

    /* Count the columns of the result set */

    rc = SQLNumResultCols(hStmt, &nColumns);
    if (!SQL_SUCCEEDED(rc)) {
	TransferSQLError(interp, SQL_HANDLE_STMT, hStmt,
................................................................................
					  Tcl_DStringLength(&colNameDS));

	    /* Test if column name is unique */

	    for (;;) {
		nameEntry = Tcl_CreateHashEntry(&nameHash,
						Tcl_GetString(colNameObj),
						&new);
		if (new) {
		    Tcl_SetHashValue(nameEntry, (ClientData) 1);
		    break;
		}

		/*
		 * Non-unique name - append a # and the number of times
		 * we've seen it before.
................................................................................
			      sdata->params[nBound].dataType,
			      sdata->params[nBound].precision,
			      sdata->params[nBound].scale,
			      rdata->bindStrings[nBound],
			      paramExternalLen,
			      rdata->bindStringLengths + nBound);
	if (!SQL_SUCCEEDED(rc)) {
	    char* info = ckalloc(80 * strlen(paramName));
	    sprintf(info, "(binding the '%s' parameter)", paramName);
	    TransferSQLError(interp, SQL_HANDLE_STMT, rdata->hStmt, info);
	    ckfree(info);
	    return TCL_ERROR;
	}
    }

................................................................................
				  -1);
		break;
	    }
	    switch(errorMessageStatus) {
	    case SQL_SUCCESS:
	    case SQL_SUCCESS_WITH_INFO:
		for (j = 0; OdbcErrorCodeNames[j].name != NULL; ++j) {
		    if (OdbcErrorCodeNames[j].value == errorCode) {
			break;
		    }
		}
		if (OdbcErrorCodeNames[j].name == NULL) {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
					     Tcl_NewStringObj("?", -1));
		} else {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
			Tcl_NewStringObj(OdbcErrorCodeNames[j].name, -1));
		}
		Tcl_ListObjAppendElement(NULL, errorCodeObj,
					 Tcl_NewWideIntObj(errorCode));

	    case SQL_NO_DATA:
	    case SQL_ERROR:
		finished = 1;
		break;
	    }

	    sep = "\n";
................................................................................
				  -1);
		break;
	    }
	    switch(errorMessageStatus) {
	    case SQL_SUCCESS:
	    case SQL_SUCCESS_WITH_INFO:
		for (j = 0; OdbcErrorCodeNames[j].name != NULL; ++j) {
		    if (OdbcErrorCodeNames[j].value == errorCode) {
			break;
		    }
		}
		if (OdbcErrorCodeNames[j].name == NULL) {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
					     Tcl_NewStringObj("?", -1));
		} else {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
			Tcl_NewStringObj(OdbcErrorCodeNames[j].name, -1));
		}
		Tcl_ListObjAppendElement(NULL, errorCodeObj,
					 Tcl_NewWideIntObj(errorCode));


	    case SQL_NO_DATA:
	    case SQL_ERROR:
		finished = 1;
		break;
	    }

	    sep = "\n";
................................................................................
 * Side effects:
 *	Creates the ::tdbc::odbc namespace and the commands that reside in it.
 *	Initializes the ODBC environment.
 *
 *-----------------------------------------------------------------------------
 */




extern DLLEXPORT int
Tdbcodbc_Init(
    Tcl_Interp* interp		/* Tcl interpreter */
) {
    SQLHENV hEnv;		/* ODBC environemnt */
    PerInterpData* pidata;	/* Per-interpreter data for this package */
    Tcl_Obj* nameObj;		/* Name of a class or method being looked up */
    Tcl_Object curClassObject;  /* Tcl_Object representing the current class */
................................................................................
	Tcl_CreateObjCommand(interp, "tdbc::odbc::datasource",
			     DatasourceObjCmdA, NULL, NULL);
    }

    DismissHEnv();
    return TCL_OK;
}



 
/*
 *-----------------------------------------------------------------------------
 *
 * DeletePerInterpData --
 *
 *	Delete per-interpreter data when the ODBC package is finalized






|







 







|







 







|







 







|









|







 







|
|







 







|







 







|












|







 







|













>







 







>
>
>
|







 







>
>
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
....
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
....
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
....
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
....
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
....
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
....
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
....
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
....
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
static Tcl_LoadHandle odbcLoadHandle = NULL;
				/* Handle to the ODBC client library */
static Tcl_LoadHandle odbcInstLoadHandle = NULL;
				/* Handle to the ODBC installer library */
static SQLHENV hEnv = SQL_NULL_HENV;
				/* Handle to the global ODBC environment */
static int hEnvRefCount = 0;	/* Reference count on the global environment */
static size_t sizeofSQLWCHAR = sizeof(SQLWCHAR);
				/* Preset, will be autodetected later */

/*
 * Objects to create within the literal pool
 */

const char* const LiteralValues[] = {
................................................................................

/*
 * Structure for looking up a string that maps to an ODBC constant
 */

typedef struct OdbcConstant {
    const char* name;		/* Constant name */
    int value;		/* Constant value */
} OdbcConstant;

/*
 * Constants for the directions of parameter transmission
 */

const static OdbcConstant OdbcParamDirections[] = {
................................................................................
		    static const char BE16sig[] = {
			'\0', '#', '\0', '#'
		    };
		    static const char LE16sig[] = {
			'#', '\0', '#', '\0'
		    };

		    if ((size_t)infoLen > sizeof(info)) {
			infoLen = sizeof(info);
		    }
		    for (i = 0; i < infoLen; i++) {
			if (info[i] >= '0' && info[i] <= '9') {
			    info[i] = '#';
			}
		    }
................................................................................
				/* Name of the current column */
    Tcl_DString colNameDS;	/* Name of the current column, translated */
    Tcl_Obj* colNameObj;	/* Name of the current column, packaged in
				 * a Tcl_Obj */
    Tcl_HashTable nameHash;	/* Hash table to manage column name
				 * uniqueness. */
    Tcl_HashEntry* nameEntry;	/* Hash table entry for the current name */
    int isNew;			/* Flag that column name is unique */
    int count;			/* Count to append to the name */
    char numbuf[16];		/* Buffer to hold the appended count */
    SQLSMALLINT i;
    int retry;
    int status = TCL_ERROR;

    /* Create a hash table to manage column name uniqueness */

    Tcl_InitHashTable(&nameHash, TCL_STRING_KEYS);
    nameEntry = Tcl_CreateHashEntry(&nameHash, "", &isNew);
    Tcl_SetHashValue(nameEntry, (ClientData) 0);

    /* Count the columns of the result set */

    rc = SQLNumResultCols(hStmt, &nColumns);
    if (!SQL_SUCCEEDED(rc)) {
	TransferSQLError(interp, SQL_HANDLE_STMT, hStmt,
................................................................................
					  Tcl_DStringLength(&colNameDS));

	    /* Test if column name is unique */

	    for (;;) {
		nameEntry = Tcl_CreateHashEntry(&nameHash,
						Tcl_GetString(colNameObj),
						&isNew);
		if (isNew) {
		    Tcl_SetHashValue(nameEntry, (ClientData) 1);
		    break;
		}

		/*
		 * Non-unique name - append a # and the number of times
		 * we've seen it before.
................................................................................
			      sdata->params[nBound].dataType,
			      sdata->params[nBound].precision,
			      sdata->params[nBound].scale,
			      rdata->bindStrings[nBound],
			      paramExternalLen,
			      rdata->bindStringLengths + nBound);
	if (!SQL_SUCCEEDED(rc)) {
	    char* info = (char *)ckalloc(80 * strlen(paramName));
	    sprintf(info, "(binding the '%s' parameter)", paramName);
	    TransferSQLError(interp, SQL_HANDLE_STMT, rdata->hStmt, info);
	    ckfree(info);
	    return TCL_ERROR;
	}
    }

................................................................................
				  -1);
		break;
	    }
	    switch(errorMessageStatus) {
	    case SQL_SUCCESS:
	    case SQL_SUCCESS_WITH_INFO:
		for (j = 0; OdbcErrorCodeNames[j].name != NULL; ++j) {
		    if (OdbcErrorCodeNames[j].value == (int)errorCode) {
			break;
		    }
		}
		if (OdbcErrorCodeNames[j].name == NULL) {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
					     Tcl_NewStringObj("?", -1));
		} else {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
			Tcl_NewStringObj(OdbcErrorCodeNames[j].name, -1));
		}
		Tcl_ListObjAppendElement(NULL, errorCodeObj,
					 Tcl_NewWideIntObj(errorCode));
		/* FALLTHRU */
	    case SQL_NO_DATA:
	    case SQL_ERROR:
		finished = 1;
		break;
	    }

	    sep = "\n";
................................................................................
				  -1);
		break;
	    }
	    switch(errorMessageStatus) {
	    case SQL_SUCCESS:
	    case SQL_SUCCESS_WITH_INFO:
		for (j = 0; OdbcErrorCodeNames[j].name != NULL; ++j) {
		    if (OdbcErrorCodeNames[j].value == (int)errorCode) {
			break;
		    }
		}
		if (OdbcErrorCodeNames[j].name == NULL) {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
					     Tcl_NewStringObj("?", -1));
		} else {
		    Tcl_ListObjAppendElement(NULL, errorCodeObj,
			Tcl_NewStringObj(OdbcErrorCodeNames[j].name, -1));
		}
		Tcl_ListObjAppendElement(NULL, errorCodeObj,
					 Tcl_NewWideIntObj(errorCode));

		/* FALLTHRU */
	    case SQL_NO_DATA:
	    case SQL_ERROR:
		finished = 1;
		break;
	    }

	    sep = "\n";
................................................................................
 * Side effects:
 *	Creates the ::tdbc::odbc namespace and the commands that reside in it.
 *	Initializes the ODBC environment.
 *
 *-----------------------------------------------------------------------------
 */

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */
DLLEXPORT int
Tdbcodbc_Init(
    Tcl_Interp* interp		/* Tcl interpreter */
) {
    SQLHENV hEnv;		/* ODBC environemnt */
    PerInterpData* pidata;	/* Per-interpreter data for this package */
    Tcl_Obj* nameObj;		/* Name of a class or method being looked up */
    Tcl_Object curClassObject;  /* Tcl_Object representing the current class */
................................................................................
	Tcl_CreateObjCommand(interp, "tdbc::odbc::datasource",
			     DatasourceObjCmdA, NULL, NULL);
    }

    DismissHEnv();
    return TCL_OK;
}
#ifdef __cplusplus
}
#endif  /* __cplusplus */
 
/*
 *-----------------------------------------------------------------------------
 *
 * DeletePerInterpData --
 *
 *	Delete per-interpreter data when the ODBC package is finalized

Changes to win/makefile.vc.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#   nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir
#   nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir install
#   nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir test
#
# For other build options (debug, static etc.)
# See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for
# detailed documentation.
# 
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------

PROJECT = tdbcodbc
# Tcl 8.6 etc. compile with /DUNICODE. TDBC pre-nmake reform compiled






|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#   nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir
#   nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir install
#   nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\installdir test
#
# For other build options (debug, static etc.)
# See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for
# detailed documentation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#------------------------------------------------------------------------------

PROJECT = tdbcodbc
# Tcl 8.6 etc. compile with /DUNICODE. TDBC pre-nmake reform compiled