tdbc::postgres

Check-in [a6e4b1fd92]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Fix a critical memory leak in resultset initialization. Change uses of ClientData for integers to the PTR2INT and INT2PTR macros, to avoid compiler warnings. Update configure.in to enable these macros, which require additional data types to be present. Advance patchlevel to 1.0.3
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | tdbcpostgres-1-0-3
Files: files | file ages | folders
SHA1: a6e4b1fd92b990ac4b44a0686cb57326fd1d6e7a
User & Date: kennykb 2014-11-29 20:05:22
Context
2015-01-26
19:04
TEA/autconf update check-in: 193a370ed6 user: dgp tags: trunk, tdbcpostgres-1-0-3
2014-11-29
20:05
Fix a critical memory leak in resultset initialization. Change uses of ClientData for integers to the PTR2INT and INT2PTR macros, to avoid compiler warnings. Update configure.in to enable these macros, which require additional data types to be present. Advance patchlevel to 1.0.3 check-in: a6e4b1fd92 user: kennykb tags: trunk, tdbcpostgres-1-0-3
2014-10-23
20:09
TEA update; Bump to 1.0.2 check-in: a1a8c48060 user: dgp tags: trunk, tdbcpostgres-1-0-2
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.





1
2
3
4
5
6
7



2014-10-23  Don Porter  <[email protected]>

	* configure.in:
	* README:	Advanced version number to 1.0.2.
	* configure: 	TEA update; autoconf 2.68

	* Makefile.in:	At some point docs we're written.  Put them in dist.
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
*** Now that tdbcpostgres is under Fossil control, the ChangeLog is
    no longer being maintained. Please refer to the change history at
    http://core.tcl.tk/tdbcpostgres/timeline/

2014-10-23  Don Porter  <[email protected]>

	* configure.in:
	* README:	Advanced version number to 1.0.2.
	* configure: 	TEA update; autoconf 2.68

	* Makefile.in:	At some point docs we're written.  Put them in dist.

Changes to README.

1
2
3
4
5
6
7
8
9
10
README: tdbcpostgres

    This is the 1.0.2 source distribution of the driver for Tcl
    Database Connectivity (TDBC) to access Postgres databases. TDBC and
    its drivers are available from a Fossil version control repository
    at http://tdbc.tcl.tk/

RCS: @(#) $Id: $

1. Introduction

|







1
2
3
4
5
6
7
8
9
10
README: tdbcpostgres

    This is the 1.0.3 source distribution of the driver for Tcl
    Database Connectivity (TDBC) to access Postgres databases. TDBC and
    its drivers are available from a Fossil version control repository
    at http://tdbc.tcl.tk/

RCS: @(#) $Id: $

1. Introduction

Changes to configure.

more than 10,000 changes

Changes to configure.in.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
183
184
185
186
187
188
189






































190
191
192
193
194
195
196
# Set your package name and version numbers here.
#
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
# set as provided.  These will also be added as -D defs in your Makefile
# so you can encode the package version directly into the source files.
#-----------------------------------------------------------------------

AC_INIT([tdbcpostgres], [1.0.2])

#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
#--------------------------------------------------------------------

................................................................................
# can't for some reason, remove this definition.  If you aren't using
# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
# link against the non-stubbed Tcl library.  Add Tk too if necessary.
#--------------------------------------------------------------------

AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])







































#--------------------------------------------------------------------
# Locate the ws2_32 library; we need it for ntohs and friends
#--------------------------------------------------------------------

AC_CHECK_LIB(ws2_32,main,TEA_ADD_LIBS([-lws2_32]),[
    AC_CHECK_LIB(winsock,main,TEA_ADD_LIBS([-lwinsock]))






|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# Set your package name and version numbers here.
#
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
# set as provided.  These will also be added as -D defs in your Makefile
# so you can encode the package version directly into the source files.
#-----------------------------------------------------------------------

AC_INIT([tdbcpostgres], [1.0.3])

#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
#--------------------------------------------------------------------

................................................................................
# can't for some reason, remove this definition.  If you aren't using
# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
# link against the non-stubbed Tcl library.  Add Tk too if necessary.
#--------------------------------------------------------------------

AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])

#--------------------------------------------------------------------
# We need the INT2PTR and PTR2INT macros, so make sure that intptr_t
# is defined.
#--------------------------------------------------------------------

AC_CHECK_HEADERS(stdint.h sys/types.h)
AC_CHECK_TYPE([intptr_t], [
    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_intptr_t" != none; then
	AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
	   type wide enough to hold a pointer.])
    fi
])
AC_CHECK_TYPE([uintptr_t], [
    AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_uintptr_t" != none; then
	AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
	   type wide enough to hold a pointer.])
    fi
])

#--------------------------------------------------------------------
# Locate the ws2_32 library; we need it for ntohs and friends
#--------------------------------------------------------------------

AC_CHECK_LIB(ws2_32,main,TEA_ADD_LIBS([-lws2_32]),[
    AC_CHECK_LIB(winsock,main,TEA_ADD_LIBS([-lwinsock]))

Changes to generic/tdbcpostgres.c.

23
24
25
26
27
28
29



30
31
32
33
34
35
36
..
49
50
51
52
53
54
55

























56
57
58
59
60
61
62
....
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
....
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
....
2884
2885
2886
2887
2888
2889
2890


2891
2892
2893
2894
2895
2896
2897
....
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
....
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
....
3402
3403
3404
3405
3406
3407
3408







#include <tdbc.h>

#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif




#ifdef USE_NATIVE_POSTGRES
#include <libpq-fe.h>
#else
#include "fakepq.h"
#endif

................................................................................
#include <netinet/in.h>
#endif

#ifdef _MSC_VER
#define snprintf _snprintf
#endif


























/* Static data contained within this file */

static Tcl_Mutex pgMutex;	/* Mutex protecting per-process structures */
static int pgRefCount = 0;	/* Reference count for the PG load handle */
static Tcl_LoadHandle pgLoadHandle = NULL;
				/* Load handle of the PG library */

................................................................................
	    Tcl_HashEntry* entry;
	    fieldName = PQfname(result, i);
	    nameObj = Tcl_NewStringObj(fieldName, -1);
	    Tcl_IncrRefCount(nameObj);
	    entry =
		Tcl_CreateHashEntry(&names, fieldName, &new);
	    while (!new) {
		count = (int) Tcl_GetHashValue(entry);
		++count;
		Tcl_SetHashValue(entry, (ClientData) count);
		sprintf(numbuf, "#%d", count);
		Tcl_AppendToObj(nameObj, numbuf, -1);
		entry = Tcl_CreateHashEntry(&names, Tcl_GetString(nameObj),
					    &new);
	    }
	    Tcl_SetHashValue(entry, (ClientData) count);
	    Tcl_ListObjAppendElement(NULL, retval, nameObj);
	    Tcl_DecrRefCount(nameObj);
	}
    }
    Tcl_DeleteHashTable(&names);
    return retval;
}
................................................................................
			   literals[LIT_INOUT]);
	    break;
	default:
	    break;
	}
	typeHashEntry =
	    Tcl_FindHashEntry(&(pidata->typeNumHash),
			      (const char*) (sdata->paramDataTypes[i]));
	if (typeHashEntry != NULL) {
	    dataTypeName = (Tcl_Obj*) Tcl_GetHashValue(typeHashEntry);
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_TYPE], dataTypeName);
	}
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_PRECISION],
		       Tcl_NewIntObj(sdata->params[i].precision));
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_SCALE],
................................................................................
	    Tcl_DecrRefCount(paramTempObjs[i]);
	}
    }

    ckfree((char*)paramValues);
    ckfree((char*)paramLengths);
    ckfree((char*)paramFormats);



    return status;
    
}
 
/*
 *-----------------------------------------------------------------------------
................................................................................
ResultSetNextrowMethod(
    ClientData clientData,	/* Not used */
    Tcl_Interp* interp,		/* Tcl interpreter */
    Tcl_ObjectContext context,	/* Object context  */
    int objc, 			/* Parameter count */
    Tcl_Obj *const objv[]	/* Parameter vector */
) {
    int lists = (int) clientData;

    Tcl_Object thisObject = Tcl_ObjectContextObject(context);
				/* The current result set object */
    ResultSetData* rdata = (ResultSetData*)
	Tcl_ObjectGetMetadata(thisObject, &resultSetDataType);
				/* Data pertaining to the current result set */
    StatementData* sdata = (StatementData*) rdata->sdata;
................................................................................
	Tcl_IncrRefCount(pidata->literals[i]);
    }
    Tcl_InitHashTable(&(pidata->typeNumHash), TCL_ONE_WORD_KEYS);
    for (i = 0; dataTypes[i].name != NULL; ++i) {
	int new;
	Tcl_HashEntry* entry =
	    Tcl_CreateHashEntry(&(pidata->typeNumHash), 
				(const char*) (int) (dataTypes[i].oid),
				&new);
	Tcl_Obj* nameObj = Tcl_NewStringObj(dataTypes[i].name, -1);
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(entry, (ClientData) nameObj);
    }


................................................................................
   if (--pgRefCount == 0) {
       Tcl_FSUnloadFile(NULL, pgLoadHandle);
       pgLoadHandle = NULL;
   }
   Tcl_MutexUnlock(&pgMutex);

}













>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|

|





|







 







|







 







>
>







 







|







 







|







 







>
>
>
>
>
>
>
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
....
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
....
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
....
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
....
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
....
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
....
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
#include <tdbc.h>

#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#    include <sys/types.h>
#endif

#ifdef USE_NATIVE_POSTGRES
#include <libpq-fe.h>
#else
#include "fakepq.h"
#endif

................................................................................
#include <netinet/in.h>
#endif

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

/*
 * Macros used to cast between pointers and integers (e.g. when storing an int
 * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
 * to/from pointer from/to integer of different size".
 */

#if !defined(INT2PTR) && !defined(PTR2INT)
#   if defined(HAVE_INTPTR_T) || defined(intptr_t)
#	define INT2PTR(p) ((void *)(intptr_t)(p))
#	define PTR2INT(p) ((int)(intptr_t)(p))
#   else
#	define INT2PTR(p) ((void *)(p))
#	define PTR2INT(p) ((int)(p))
#   endif
#endif
#if !defined(UINT2PTR) && !defined(PTR2UINT)
#   if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
#	define UINT2PTR(p) ((void *)(uintptr_t)(p))
#	define PTR2UINT(p) ((unsigned int)(uintptr_t)(p))
#   else
#	define UINT2PTR(p) ((void *)(p))
#	define PTR2UINT(p) ((unsigned int)(p))
#   endif
#endif

/* Static data contained within this file */

static Tcl_Mutex pgMutex;	/* Mutex protecting per-process structures */
static int pgRefCount = 0;	/* Reference count for the PG load handle */
static Tcl_LoadHandle pgLoadHandle = NULL;
				/* Load handle of the PG library */

................................................................................
	    Tcl_HashEntry* entry;
	    fieldName = PQfname(result, i);
	    nameObj = Tcl_NewStringObj(fieldName, -1);
	    Tcl_IncrRefCount(nameObj);
	    entry =
		Tcl_CreateHashEntry(&names, fieldName, &new);
	    while (!new) {
	        count = PTR2INT(Tcl_GetHashValue(entry));
		++count;
		Tcl_SetHashValue(entry, INT2PTR(count));
		sprintf(numbuf, "#%d", count);
		Tcl_AppendToObj(nameObj, numbuf, -1);
		entry = Tcl_CreateHashEntry(&names, Tcl_GetString(nameObj),
					    &new);
	    }
	    Tcl_SetHashValue(entry, INT2PTR(count));
	    Tcl_ListObjAppendElement(NULL, retval, nameObj);
	    Tcl_DecrRefCount(nameObj);
	}
    }
    Tcl_DeleteHashTable(&names);
    return retval;
}
................................................................................
			   literals[LIT_INOUT]);
	    break;
	default:
	    break;
	}
	typeHashEntry =
	    Tcl_FindHashEntry(&(pidata->typeNumHash),
			      INT2PTR(sdata->paramDataTypes[i]));
	if (typeHashEntry != NULL) {
	    dataTypeName = (Tcl_Obj*) Tcl_GetHashValue(typeHashEntry);
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_TYPE], dataTypeName);
	}
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_PRECISION],
		       Tcl_NewIntObj(sdata->params[i].precision));
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_SCALE],
................................................................................
	    Tcl_DecrRefCount(paramTempObjs[i]);
	}
    }

    ckfree((char*)paramValues);
    ckfree((char*)paramLengths);
    ckfree((char*)paramFormats);
    ckfree((char*)paramNeedsFreeing);
    ckfree((char*)paramTempObjs);

    return status;
    
}
 
/*
 *-----------------------------------------------------------------------------
................................................................................
ResultSetNextrowMethod(
    ClientData clientData,	/* Not used */
    Tcl_Interp* interp,		/* Tcl interpreter */
    Tcl_ObjectContext context,	/* Object context  */
    int objc, 			/* Parameter count */
    Tcl_Obj *const objv[]	/* Parameter vector */
) {
    int lists = PTR2INT(clientData);

    Tcl_Object thisObject = Tcl_ObjectContextObject(context);
				/* The current result set object */
    ResultSetData* rdata = (ResultSetData*)
	Tcl_ObjectGetMetadata(thisObject, &resultSetDataType);
				/* Data pertaining to the current result set */
    StatementData* sdata = (StatementData*) rdata->sdata;
................................................................................
	Tcl_IncrRefCount(pidata->literals[i]);
    }
    Tcl_InitHashTable(&(pidata->typeNumHash), TCL_ONE_WORD_KEYS);
    for (i = 0; dataTypes[i].name != NULL; ++i) {
	int new;
	Tcl_HashEntry* entry =
	    Tcl_CreateHashEntry(&(pidata->typeNumHash), 
				INT2PTR(dataTypes[i].oid),
				&new);
	Tcl_Obj* nameObj = Tcl_NewStringObj(dataTypes[i].name, -1);
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(entry, (ClientData) nameObj);
    }


................................................................................
   if (--pgRefCount == 0) {
       Tcl_FSUnloadFile(NULL, pgLoadHandle);
       pgLoadHandle = NULL;
   }
   Tcl_MutexUnlock(&pgMutex);

}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * End:
 */