tdbc::mysql

Check-in [0048009d31]
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:Adapt code for cygwin, which uses "cyg" as mysql library prefix and inserts library version before in stead of after .dll. Eliminate various end-of-line spaces
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0048009d31f9f1e8645286a0a89c681b81019bcc
User & Date: jan.nijtmans 2015-06-26 11:58:57
References
2016-03-10
02:38 New ticket [f3c6ec0369] segfault on Linux when no mysql libs available. artifact: 3d2c16b4dc user: anonymous
Context
2015-06-26
13:03
Make mysqlStubs a 'const'ant, as only Tcl_LoadFile() is allowed to fill this table. check-in: c4394a8239 user: jan.nijtmans tags: trunk
11:58
Adapt code for cygwin, which uses "cyg" as mysql library prefix and inserts library version before in stead of after .dll. Eliminate various end-of-line spaces check-in: 0048009d31 user: jan.nijtmans tags: trunk
2015-05-08
15:21
Fix 2ca1f6da0d: Windows compilation in pkgs fails when using msys/configure check-in: de252f437f user: jan.nijtmans tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.

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
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
374
375
376
377
378
379
380
381
382
383
384
			go through accessor functions that hit the correct
			versions of the structures according to the client
			library version. (Tcl can provide ABI stability,
			even if MySQL can't!)
	* configure.in: Advance release to 1.0b15.1
	* README:	Advance release to 1.0b15.1
	* configure:	autoconf-2.59
	
2010-05-10  Kevin B. Kenny  <[email protected]>

	* aclocal.m4:	Synchronize with tdbc.
	* configure.in:	Advance TEA version to 3.7. Advance release to 1.0b15.
			Corrected the TDBC stub library specification so that 
			it works under MSVC.
	* generic/mysqlStubDefs.txt:
			Split out the linkage convention so that 
			genExtStubs.tcl can generate syntactically correct
			VC++ pointer-to-function declarations.
	* generic/mysqlStubInit.c:
	* generic/mysqlStubs.h:
			Regenerate
	* generic/tdbcmysql.c:
			Added code to silence VC++ warnings.
	* README:	Advance release to 1.0b15
	* tclconfig/:	Advance to TEA 3.7
	* configure:	autoconf-2.59
	
2010-05-10  Andreas Kupries  <[email protected]>

	* generic/tdbcmysql.c: Fixed violations of strict C89.
	* Makefile.in: Removed attempt to generate a stub library. Drivers
	  do not export stub tables.

2010-05-07  Andreas Kupries  <[email protected]>
................................................................................
		Definitions of the routines to be resolved when loading
		the MySQL library at run time.
	* generic/tdbcmysql.c:
		Changed tdbc::mysql to load the MySQL library at run time
		and to have no compile-time dependencies on MySQL.
	* tests/tdbcodbc.test (tdbc::mysql-14.8):
		Corrected a misnamed test.
	
2010-04-25  Kevin B. Kenny  <[email protected]>

	* configure.in: Adjusted TDBC_* environment vars to be tdbc_*
	* README:	for better TEA compatibility. Advanced version number
			to 1.0b14.
	* configure:	autoconf-2.59
	
2009-09-29  Kevin B. Kenny  <[email protected]>

	* tests/tdbcmysql.test: Changed all TEST_* environment variables
				to TDBCMYSQL_* for easier high-level scripting
				of the tests.
	
2009-09-20  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b13
	* configure:		autoconf-2.59
	
2009-07-03  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b12
	* configure:		autoconf-2.59
	
2009-05-29  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b11
	* configure:		autoconf-2.59
	
2009-04-19  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c: Silenced a compiler warning about 'fields'
	                       being used uninitialized.
	* doc/tdbc_mysql.n: Added missing documentation for 'new' constructors.

2009-04-18  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c: Changed so that an inappropriate access to
	                       an array or a failing read trace yields NULL.
	* tests/tdbcmysql.test: Revised test cases according to the above 
				change.
	* doc/tdbc_mysql.n: Made changes so that NROFF formatting matches
	                    the Tcl standard.
	
2009-04-16  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b10
	* configure:		autoconf-2.59

	* generic/tdbcmysql.c: Reworked the allocation of result buffers
................................................................................
			       are not allocated per row. Pushed binding the
	                       results up before mysql_stmt_execute,
	                       avoiding a crash if the same statement handle
	                       has been used before [Ticket 39a78606aa].
			       No update made to test suite because
			       valgrind detected the error with existing
			       tests on a -DPURIFY build.
	
2009-03-03  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c:
	* library/tdbcmysql.tcl: Replaced 'init' methods with constructors
	written in C.  Added 'statementCreate' and 'resultSetCreate' forwarding
	in place of the 'statementClass' and 'resultSetClass' variables.
	Removed some classes that were the result of overeager copying
	from tclodbc. Replaced 'my variable' with variables declared at
	class level.
	
2009-02-14  Kevin B. Kenny  <[email protected]>

	* doc/tdbc_mysql.n:	Many small format changes to make 'man2html'
				work.
	* README:
	* configure.in:		Advance version number to 1.0b8
	* configure:		autoconf-2.59
	
2009-02-01  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c: 
	* configure.in: Changed the <my_global.h> tests to use the
	correct conditionals on mingw.
	* configure: Autoconf 2.59
	
2009-01-31  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in: Advanced version to 1.0b7.
	* configure: Regenerated.
	* generic/tdbcmysql.c: Revised errorCode generation to be
	more [try]-friendly. Changed include to <mysql/mysql.h> so that
	the include path isn't necessary.
	* tests/tdbcmysql.test: Added test flags so that a nonstandard port
	or socket can be specified. Changed errorCode-dependent tests to
	look for the new form of errorCode.
	
2009-01-05  Kevin B. Kenny  <[email protected]>

	* README: Added a few more hints for building on Windows.
	* configure.in: Changes to make tdbcmysql build on Windows.
	* generic/tdbcmysql.c: Changed to #include <my_global.h> on Windows.
	Advanced release to 1.0b6
	* configure: autoconf 2.59
	
2009-01-04  Kevin B. Kenny  <[email protected]>

	* README:
	* Makefile.in:
	* doc/tdbc_mysql.n: Updated so that files are no longer clones
	of the 'tdbcodbc' package. Added installation and distribution code.
	* configure.in: Advanced version to 1.0b5
................................................................................
	do direct binary conversions of integers, floating point numbers,
	and bit strings. Added checks for binary data on results.
	Added disambiguation of duplicated colmn names.
	* tests/tdbcmysql.test: Revised test cases to include all the
	MySQL data types handled in this driver. Added a test case that
	column names are correctly disambiguated.
	* configure: autoconf 2.59
	
2009-01-02  Kevin B. Kenny  <[email protected]>

	Initial baseline of a TDBC driver for MySQL.






|




|


|










|







 







|






|





|





|





|





|










|



|







 







|









|







|


|



|











|







|







 







|



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
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
374
375
376
377
378
379
380
381
382
383
384
			go through accessor functions that hit the correct
			versions of the structures according to the client
			library version. (Tcl can provide ABI stability,
			even if MySQL can't!)
	* configure.in: Advance release to 1.0b15.1
	* README:	Advance release to 1.0b15.1
	* configure:	autoconf-2.59

2010-05-10  Kevin B. Kenny  <[email protected]>

	* aclocal.m4:	Synchronize with tdbc.
	* configure.in:	Advance TEA version to 3.7. Advance release to 1.0b15.
			Corrected the TDBC stub library specification so that
			it works under MSVC.
	* generic/mysqlStubDefs.txt:
			Split out the linkage convention so that
			genExtStubs.tcl can generate syntactically correct
			VC++ pointer-to-function declarations.
	* generic/mysqlStubInit.c:
	* generic/mysqlStubs.h:
			Regenerate
	* generic/tdbcmysql.c:
			Added code to silence VC++ warnings.
	* README:	Advance release to 1.0b15
	* tclconfig/:	Advance to TEA 3.7
	* configure:	autoconf-2.59

2010-05-10  Andreas Kupries  <[email protected]>

	* generic/tdbcmysql.c: Fixed violations of strict C89.
	* Makefile.in: Removed attempt to generate a stub library. Drivers
	  do not export stub tables.

2010-05-07  Andreas Kupries  <[email protected]>
................................................................................
		Definitions of the routines to be resolved when loading
		the MySQL library at run time.
	* generic/tdbcmysql.c:
		Changed tdbc::mysql to load the MySQL library at run time
		and to have no compile-time dependencies on MySQL.
	* tests/tdbcodbc.test (tdbc::mysql-14.8):
		Corrected a misnamed test.

2010-04-25  Kevin B. Kenny  <[email protected]>

	* configure.in: Adjusted TDBC_* environment vars to be tdbc_*
	* README:	for better TEA compatibility. Advanced version number
			to 1.0b14.
	* configure:	autoconf-2.59

2009-09-29  Kevin B. Kenny  <[email protected]>

	* tests/tdbcmysql.test: Changed all TEST_* environment variables
				to TDBCMYSQL_* for easier high-level scripting
				of the tests.

2009-09-20  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b13
	* configure:		autoconf-2.59

2009-07-03  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b12
	* configure:		autoconf-2.59

2009-05-29  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b11
	* configure:		autoconf-2.59

2009-04-19  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c: Silenced a compiler warning about 'fields'
	                       being used uninitialized.
	* doc/tdbc_mysql.n: Added missing documentation for 'new' constructors.

2009-04-18  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c: Changed so that an inappropriate access to
	                       an array or a failing read trace yields NULL.
	* tests/tdbcmysql.test: Revised test cases according to the above
				change.
	* doc/tdbc_mysql.n: Made changes so that NROFF formatting matches
	                    the Tcl standard.

2009-04-16  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in:		Advance version number to 1.0b10
	* configure:		autoconf-2.59

	* generic/tdbcmysql.c: Reworked the allocation of result buffers
................................................................................
			       are not allocated per row. Pushed binding the
	                       results up before mysql_stmt_execute,
	                       avoiding a crash if the same statement handle
	                       has been used before [Ticket 39a78606aa].
			       No update made to test suite because
			       valgrind detected the error with existing
			       tests on a -DPURIFY build.

2009-03-03  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c:
	* library/tdbcmysql.tcl: Replaced 'init' methods with constructors
	written in C.  Added 'statementCreate' and 'resultSetCreate' forwarding
	in place of the 'statementClass' and 'resultSetClass' variables.
	Removed some classes that were the result of overeager copying
	from tclodbc. Replaced 'my variable' with variables declared at
	class level.

2009-02-14  Kevin B. Kenny  <[email protected]>

	* doc/tdbc_mysql.n:	Many small format changes to make 'man2html'
				work.
	* README:
	* configure.in:		Advance version number to 1.0b8
	* configure:		autoconf-2.59

2009-02-01  Kevin B. Kenny  <[email protected]>

	* generic/tdbcmysql.c:
	* configure.in: Changed the <my_global.h> tests to use the
	correct conditionals on mingw.
	* configure: Autoconf 2.59

2009-01-31  Kevin B. Kenny  <[email protected]>

	* README:
	* configure.in: Advanced version to 1.0b7.
	* configure: Regenerated.
	* generic/tdbcmysql.c: Revised errorCode generation to be
	more [try]-friendly. Changed include to <mysql/mysql.h> so that
	the include path isn't necessary.
	* tests/tdbcmysql.test: Added test flags so that a nonstandard port
	or socket can be specified. Changed errorCode-dependent tests to
	look for the new form of errorCode.

2009-01-05  Kevin B. Kenny  <[email protected]>

	* README: Added a few more hints for building on Windows.
	* configure.in: Changes to make tdbcmysql build on Windows.
	* generic/tdbcmysql.c: Changed to #include <my_global.h> on Windows.
	Advanced release to 1.0b6
	* configure: autoconf 2.59

2009-01-04  Kevin B. Kenny  <[email protected]>

	* README:
	* Makefile.in:
	* doc/tdbc_mysql.n: Updated so that files are no longer clones
	of the 'tdbcodbc' package. Added installation and distribution code.
	* configure.in: Advanced version to 1.0b5
................................................................................
	do direct binary conversions of integers, floating point numbers,
	and bit strings. Added checks for binary data on results.
	Added disambiguation of duplicated colmn names.
	* tests/tdbcmysql.test: Revised test cases to include all the
	MySQL data types handled in this driver. Added a test case that
	column names are correctly disambiguated.
	* configure: autoconf 2.59

2009-01-02  Kevin B. Kenny  <[email protected]>

	Initial baseline of a TDBC driver for MySQL.

Changes to Makefile.in.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
..
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
91
92
93
94
95
96
97
98
99
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261










262
263
264
265
266
267
268
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
#	replaced in the actual Makefile.
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: Makefile.in,v 1.64 2007/10/23 22:08:06 hobbs Exp $

#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
# have been added in a customized configure script.
#========================================================================

#SAMPLE_NEW_VAR	= @[email protected]

#========================================================================
# Nothing of the variables below this line should need to be changed.
# Please check the TARGETS section below to make sure the make targets
# are correct.
#========================================================================

................................................................................
srcdir		= @[email protected]
prefix		= @[email protected]
exec_prefix	= @[email protected]

bindir		= @[email protected]
libdir		= @[email protected]
includedir	= @[email protected]
datarootdir     = @[email protected]
datadir		= @[email protected]
mandir		= @[email protected]

DESTDIR		=

PKG_DIR		= $(PACKAGE_NAME)$(PACKAGE_VERSION)
pkgdatadir	= $(datadir)/$(PKG_DIR)
pkglibdir	= $(libdir)/$(PKG_DIR)
pkgincludedir	= $(includedir)/$(PKG_DIR)

top_builddir	= .

INSTALL_OPTIONS =
INSTALL         = $(SHELL) $(srcdir)/tclconfig/install-sh -c ${INSTALL_OPTIONS}
INSTALL_DATA_DIR = ${INSTALL} -d -m 755
INSTALL_PROGRAM = ${INSTALL} -m 755
INSTALL_DATA    = ${INSTALL} -m 444
INSTALL_SCRIPT  = ${INSTALL_PROGRAM}
INSTALL_LIBRARY = ${INSTALL_DATA}

PACKAGE_NAME	= @[email protected]
PACKAGE_VERSION	= @[email protected]
CC		= @[email protected]
CFLAGS_DEFAULT	= @[email protected]
CFLAGS_WARNING	= @[email protected]
EXEEXT		= @[email protected]
................................................................................
#EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
TCLLIBPATH	= $(top_builddir)
TCLSH_ENV	= TCL_LIBRARY=`@[email protected] $(TCL_SRC_DIR)/library` \
		  TDBC_LIBRARY=`@[email protected] @[email protected]`
PKG_ENV		= @[email protected]="$(EXTRA_PATH):$(@[email protected])" \
		  PATH="$(EXTRA_PATH):$(PATH)" \
		  TCLLIBPATH="$(TCLLIBPATH)" \
                  TDBCMYSQL_LIBRARY=`@[email protected] $(srcdir)/library` 

TCLSH_PROG	= @[email protected]
TCLSH   	= $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG)

#WISH_ENV	= TK_LIBRARY=`@[email protected] $(TK_SRC_DIR)/library`
#WISH_PROG	= @[email protected]
#WISH   	= $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG)

SHARED_BUILD	= @[email protected]

INCLUDES	= @[email protected] @[email protected] 
# INCLUDES	= @[email protected] @[email protected] @[email protected] @[email protected]

PKG_CFLAGS	= @[email protected]

# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.ac checks for the necessary components
# that your library may use.  TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS		= $(TCL_DEFS) @[email protected] $(PKG_CFLAGS)
DEFS		= @[email protected] $(PKG_CFLAGS)

# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
CONFIGURE_OUTPUTS = @[email protected]
CLEANFILES	= @[email protected]

CPPFLAGS	= @[email protected]
LIBS		= @[email protected] @[email protected]
AR		= @[email protected]
CFLAGS		= @[email protected]
COMPILE		= $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)

VALGRIND		= valgrind
VALGRINDARGS		= --tool=memcheck --num-callers=16 --leak-resolution=high --leak-check=yes --show-reachable=yes -v

#========================================================================
# Start of user-definable TARGETS section
#========================================================================

#========================================================================
# TEA TARGETS.  Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target inclues executable programs and
# platform-dependent libraries.  Modify these targets so that they install
# the various pieces of your package.  The make and install rules
# for the BINARIES that you specified above have already been done.
#========================================================================

all: binaries libraries doc

................................................................................
	@list='$(srcdir)/doc/*.n'; for i in $$list; do \
	    echo "Installing $$i"; \
	    rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
	done

test: binaries libraries
	$(TCLSH) `@[email protected] $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
		-load "package ifneeded tdbc::mysql $(PACKAGE_VERSION) \
			[list source `@[email protected] $(srcdir)/library/tdbcmysql.tcl`]\;[list load `@[email protected] $(PKG_LIB_FILE)` $(PACKAGE_NAME)];\
		package ifneeded tdbc ${TDBC_VERSION} \
			[list source `@[email protected] $(TDBC_BIN_DIR)/tdbc.tcl`]\;[list load `@[email protected] $(TDBC_BIN_DIR)/$(TDBC_LIB_FILE)` tdbc]"

valgrind: binaries libraries
	$(PKG_ENV) $(TCLSH_ENV) \
	LD_PRELOAD=$(PKG_LIB_FILE) \
	$(VALGRIND) $(VALGRINDARGS) \
	$(TCLSH_PROG) `@[email protected] $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
		-load "package ifneeded tdbc::mysql ${PACKAGE_VERSION} \
			[list source `@[email protected] $(srcdir)/library/tdbcmysql.tcl`]\;[list load `@[email protected] $(PKG_LIB_FILE)` $(PACKAGE_NAME)]"


shell: binaries libraries
	@$(TCLSH) $(SCRIPT)

gdb:
	$(TCLSH_ENV) $(PKG_ENV) gdb $(TCLSH_PROG) $(SCRIPT)











depend:

#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above.  That will ensure that this target is built when you
# run "make binaries".
................................................................................
# 	$(COMPILE) -c `@[email protected] $(srcdir)/generic/sample.c` -o [email protected]
#
# Setting the VPATH variable to a list of paths will cause the makefile
# to look into these paths when resolving .c to .obj dependencies.
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================

VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win

[email protected]@:
	$(COMPILE) -c `@[email protected] $<` -o [email protected]

#========================================================================
# Distribution creation
# You may need to tweak this target to make it work correctly.
................................................................................
DIST_ROOT	= /tmp/dist
DIST_DIR	= $(DIST_ROOT)/$(PKG_DIR)

dist-clean:
	rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*

dist: dist-clean
	mkdir -p $(DIST_DIR)
	cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \
		$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
		$(srcdir)/configure.ac $(DIST_DIR)/
	chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
	chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.ac

	for i in $(srcdir)/*.[ch]; do \
	    if [ -f $$i ]; then \
		cp -p $$i $(DIST_DIR)/ ; \
	    fi; \
	done;

	mkdir $(DIST_DIR)/tclconfig
	cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
		$(DIST_DIR)/tclconfig/
	chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
	chmod +x $(DIST_DIR)/tclconfig/install-sh

	mkdir $(DIST_DIR)/doc
	cp -p $(srcdir)/doc/tdbc_mysql.n $(DIST_DIR)/doc/

................................................................................
#========================================================================

#========================================================================
# Don't modify the file to clean here.  Instead, set the "CLEANFILES"
# variable in configure.ac
#========================================================================

clean:  
	-test -z "$(BINARIES)" || rm -f $(BINARIES)
	-rm -f *.$(OBJEXT) core *.core
	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)

distclean: clean
	-rm -f *.tab.c
	-rm -f $(CONFIGURE_OUTPUTS)
	-rm -f config.cache config.log config.status

#========================================================================
# Install binary object libraries.  On Windows this includes both .dll and
# .lib files.  Because the .lib files are not explicitly listed anywhere,
# we need to deduce their existence from the .dll file of the same name.
# Library files go into the lib directory.
................................................................................
# You should not have to modify this target.
#========================================================================

install-lib-binaries: binaries
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir)
	@list='$(lib_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
	    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \
	    stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
	    if test "x$$stub" = "xstub"; then \
		echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
	    else \
		echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
................................................................................
	@list='$(bin_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
	    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
	  fi; \
	done

.SUFFIXES: .c .$(OBJEXT)

Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
	cd $(top_builddir) \
	  && [email protected] CONFIG_HEADERS= $(SHELL) ./config.status

uninstall-binaries:
	list='$(lib_BINARIES)'; for p in $$list; do \
	  rm -f $(DESTDIR)$(pkglibdir)/$$p; \






<
<
<
<
<
<
<
<
<







 







|












|
|
|
|
|
|
|







 







|


|



|



|
|












|








|
<







|







 







|




<
<
<
<
<
<
<
<
<






>
>
>
>
>
>
>
>
>
>







 







|







 







|












|
|







 







|






|







 







|
|







 







<
<







7
8
9
10
11
12
13









14
15
16
17
18
19
20
..
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
...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
225
226
227
228
229
230
231
232
233
234
235
236









237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
439
440
441
442
443
444
445


446
447
448
449
450
451
452
#	replaced in the actual Makefile.
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.










#========================================================================
# Nothing of the variables below this line should need to be changed.
# Please check the TARGETS section below to make sure the make targets
# are correct.
#========================================================================

................................................................................
srcdir		= @[email protected]
prefix		= @[email protected]
exec_prefix	= @[email protected]

bindir		= @[email protected]
libdir		= @[email protected]
includedir	= @[email protected]
datarootdir	= @[email protected]
datadir		= @[email protected]
mandir		= @[email protected]

DESTDIR		=

PKG_DIR		= $(PACKAGE_NAME)$(PACKAGE_VERSION)
pkgdatadir	= $(datadir)/$(PKG_DIR)
pkglibdir	= $(libdir)/$(PKG_DIR)
pkgincludedir	= $(includedir)/$(PKG_DIR)

top_builddir	= .

INSTALL_OPTIONS	=
INSTALL		= @[email protected] ${INSTALL_OPTIONS}
INSTALL_DATA_DIR = @INSTALL[email protected]
INSTALL_DATA	= @INSTALL[email protected]
INSTALL_PROGRAM	= @INSTALL[email protected]
INSTALL_SCRIPT	= @INSTALL_[email protected]
INSTALL_LIBRARY	= @INSTALL_[email protected]

PACKAGE_NAME	= @[email protected]
PACKAGE_VERSION	= @[email protected]
CC		= @[email protected]
CFLAGS_DEFAULT	= @[email protected]
CFLAGS_WARNING	= @[email protected]
EXEEXT		= @[email protected]
................................................................................
#EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
TCLLIBPATH	= $(top_builddir)
TCLSH_ENV	= TCL_LIBRARY=`@[email protected] $(TCL_SRC_DIR)/library` \
		  TDBC_LIBRARY=`@[email protected] @[email protected]`
PKG_ENV		= @[email protected]="$(EXTRA_PATH):$(@[email protected])" \
		  PATH="$(EXTRA_PATH):$(PATH)" \
		  TCLLIBPATH="$(TCLLIBPATH)" \
		  TDBCMYSQL_LIBRARY=`@[email protected] $(srcdir)/library`

TCLSH_PROG	= @[email protected]
TCLSH		= $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG)

#WISH_ENV	= TK_LIBRARY=`@[email protected] $(TK_SRC_DIR)/library`
#WISH_PROG	= @[email protected]
#WISH		= $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG)

SHARED_BUILD	= @[email protected]

INCLUDES	= @[email protected] @[email protected]
#INCLUDES	= @[email protected] @[email protected] @[email protected] @[email protected]

PKG_CFLAGS	= @[email protected]

# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.ac checks for the necessary components
# that your library may use.  TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS		= $(TCL_DEFS) @[email protected] $(PKG_CFLAGS)
DEFS		= @[email protected] $(PKG_CFLAGS)

# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
CLEANFILES	= @[email protected]

CPPFLAGS	= @[email protected]
LIBS		= @[email protected] @[email protected]
AR		= @[email protected]
CFLAGS		= @[email protected]
COMPILE		= $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)

.SUFFIXES: .c .$(OBJEXT)


#========================================================================
# Start of user-definable TARGETS section
#========================================================================

#========================================================================
# TEA TARGETS.  Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target includes executable programs and
# platform-dependent libraries.  Modify these targets so that they install
# the various pieces of your package.  The make and install rules
# for the BINARIES that you specified above have already been done.
#========================================================================

all: binaries libraries doc

................................................................................
	@list='$(srcdir)/doc/*.n'; for i in $$list; do \
	    echo "Installing $$i"; \
	    rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
	done

test: binaries libraries
	@$(TCLSH) `@[email protected] $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
		-load "package ifneeded tdbc::mysql $(PACKAGE_VERSION) \
			[list source `@[email protected] $(srcdir)/library/tdbcmysql.tcl`]\;[list load `@[email protected] $(PKG_LIB_FILE)` $(PACKAGE_NAME)];\
		package ifneeded tdbc ${TDBC_VERSION} \
			[list source `@[email protected] $(TDBC_BIN_DIR)/tdbc.tcl`]\;[list load `@[email protected] $(TDBC_BIN_DIR)/$(TDBC_LIB_FILE)` tdbc]"










shell: binaries libraries
	@$(TCLSH) $(SCRIPT)

gdb:
	$(TCLSH_ENV) $(PKG_ENV) gdb $(TCLSH_PROG) $(SCRIPT)

VALGRINDARGS =	--tool=memcheck --num-callers=8 --leak-resolution=high \
		--leak-check=yes --show-reachable=yes -v

valgrind: binaries libraries
	$(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) \
		`@[email protected] $(srcdir)/tests/all.tcl` $(TESTFLAGS)

valgrindshell: binaries libraries
	$(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)

depend:

#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above.  That will ensure that this target is built when you
# run "make binaries".
................................................................................
# 	$(COMPILE) -c `@[email protected] $(srcdir)/generic/sample.c` -o [email protected]
#
# Setting the VPATH variable to a list of paths will cause the makefile
# to look into these paths when resolving .c to .obj dependencies.
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================

VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx

[email protected]@:
	$(COMPILE) -c `@[email protected] $<` -o [email protected]

#========================================================================
# Distribution creation
# You may need to tweak this target to make it work correctly.
................................................................................
DIST_ROOT	= /tmp/dist
DIST_DIR	= $(DIST_ROOT)/$(PKG_DIR)

dist-clean:
	rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*

dist: dist-clean
	$(INSTALL_DATA_DIR) $(DIST_DIR)
	cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \
		$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
		$(srcdir)/configure.ac $(DIST_DIR)/
	chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
	chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.ac

	for i in $(srcdir)/*.[ch]; do \
	    if [ -f $$i ]; then \
		cp -p $$i $(DIST_DIR)/ ; \
	    fi; \
	done;

	$(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig
	cp -p $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
		$(DIST_DIR)/tclconfig/
	chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
	chmod +x $(DIST_DIR)/tclconfig/install-sh

	mkdir $(DIST_DIR)/doc
	cp -p $(srcdir)/doc/tdbc_mysql.n $(DIST_DIR)/doc/

................................................................................
#========================================================================

#========================================================================
# Don't modify the file to clean here.  Instead, set the "CLEANFILES"
# variable in configure.ac
#========================================================================

clean:
	-test -z "$(BINARIES)" || rm -f $(BINARIES)
	-rm -f *.$(OBJEXT) core *.core
	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)

distclean: clean
	-rm -f *.tab.c
	-rm -f $(CONFIG_CLEAN_FILES)
	-rm -f config.cache config.log config.status

#========================================================================
# Install binary object libraries.  On Windows this includes both .dll and
# .lib files.  Because the .lib files are not explicitly listed anywhere,
# we need to deduce their existence from the .dll file of the same name.
# Library files go into the lib directory.
................................................................................
# You should not have to modify this target.
#========================================================================

install-lib-binaries: binaries
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir)
	@list='$(lib_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
	    $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \
	    stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
	    if test "x$$stub" = "xstub"; then \
		echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
	    else \
		echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
................................................................................
	@list='$(bin_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
	    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
	  fi; \
	done



Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
	cd $(top_builddir) \
	  && [email protected] CONFIG_HEADERS= $(SHELL) ./config.status

uninstall-binaries:
	list='$(lib_BINARIES)'; for p in $$list; do \
	  rm -f $(DESTDIR)$(pkglibdir)/$$p; \

Changes to README.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
rules described in the README file for tdbc. In addition to the
options described there, the 'configure' script for tdbcmysql
accepts the following two options:

    --with-mysql-includedir=PATH

	Specifies PATH as the path to the directory that contains
	'mysql.h' and related header files. 

    --with-mysql-libdir=PATH

	Specifies PATH as the path to the directory that contains
	the MySQL link libraries.

Building on Windows is tested only with msys/mingw, and only with
the version of MySQL present in XAMPP (https://sourceforge.net/projects/xampp)
You need the 'xampp-win32-devel' package as well as the 'xampp-win32'
package.

In order to build the code under msys/mingw, you need to rebuild the
import library for use by mingw. (This also requires the 'reimp' 
utility from mingw-utils.) The recipe for this step is:

    reimp -d drive:/path/to/xampp/lib/mysql/libmysql.lib
    dlltool -k -d libmysql.def -l libmysql.a
    cp libmysql.a drive:/path/to/mingw/lib

It is also convenient to make sure that the MySQL headers are available






|












|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
rules described in the README file for tdbc. In addition to the
options described there, the 'configure' script for tdbcmysql
accepts the following two options:

    --with-mysql-includedir=PATH

	Specifies PATH as the path to the directory that contains
	'mysql.h' and related header files.

    --with-mysql-libdir=PATH

	Specifies PATH as the path to the directory that contains
	the MySQL link libraries.

Building on Windows is tested only with msys/mingw, and only with
the version of MySQL present in XAMPP (https://sourceforge.net/projects/xampp)
You need the 'xampp-win32-devel' package as well as the 'xampp-win32'
package.

In order to build the code under msys/mingw, you need to rebuild the
import library for use by mingw. (This also requires the 'reimp'
utility from mingw-utils.) The recipe for this step is:

    reimp -d drive:/path/to/xampp/lib/mysql/libmysql.lib
    dlltool -k -d libmysql.def -l libmysql.a
    cp libmysql.a drive:/path/to/mingw/lib

It is also convenient to make sure that the MySQL headers are available

Changes to configure.

2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
....
2572
2573
2574
2575
2576
2577
2578






























2579
2580
2581
2582
2583
2584
2585
....
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088



6089

6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
.....
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437

#--------------------------------------------------------------------
# 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.
#--------------------------------------------------------------------

ac_aux_dir=
for ac_dir in tclconfig "$srcdir"/tclconfig; do
  if test -f "$ac_dir/install-sh"; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install-sh -c"
    break
  elif test -f "$ac_dir/install.sh"; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install.sh -c"
    break
  elif test -f "$ac_dir/shtool"; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/shtool install -c"
    break
  fi
done
if test -z "$ac_aux_dir"; then
  as_fn_error $? "cannot find install-sh, install.sh, or shtool in tclconfig \"$srcdir\"/tclconfig" "$LINENO" 5
fi

# These three variables are undocumented and unsupported,
# and are intended to be withdrawn in a future Autoconf release.
# They can cause serious problems if a builder's source tree is in a directory
# whose full name contains unusual characters.
ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.



    # TEA extensions pass this us the version of TEA they think they
    # are compatible with.
    TEA_VERSION="3.9"

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for correct TEA configuration" >&5
$as_echo_n "checking for correct TEA configuration... " >&6; }
    if test x"${PACKAGE_NAME}" = x ; then
	as_fn_error $? "
The PACKAGE_NAME variable must be defined by your TEA configure.ac" "$LINENO" 5
    fi
    if test x"3.9" = x ; then
	as_fn_error $? "
TEA version not specified." "$LINENO" 5
    elif test "3.9" != "${TEA_VERSION}" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&5
$as_echo "warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&6; }
................................................................................







































#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------


................................................................................
	fi
	PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
    done



#--------------------------------------------------------------------
# A few miscellaneous platform-specific items:
#
# Define a special symbol for Windows (BUILD_sample in this case) so
# that we create the export library with the dll.
#
# Windows creates a few extra files that need to be cleaned up.
# You can add more files to clean if your extension creates any extra
# files.



#

# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------

# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#CLEANFILES="$CLEANFILES pkgIndex.tcl"

#--------------------------------------------------------------------
# Choose which headers you need.  Extension authors should try very
# hard to only rely on the Tcl public header files.  Internal headers
# contain private data structures and are subject to change without
# notice.
................................................................................
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi


# This is a comment added to force the 'execute' permission to update
# in the Fossil repository.






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










|







 







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







 







<

<
<
<
<

<
>
>
>

>



<
<







 







<
<
<
2421
2422
2423
2424
2425
2426
2427





























2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
....
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
....
6075
6076
6077
6078
6079
6080
6081

6082




6083

6084
6085
6086
6087
6088
6089
6090
6091


6092
6093
6094
6095
6096
6097
6098
.....
10425
10426
10427
10428
10429
10430
10431




#--------------------------------------------------------------------
# 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.
#--------------------------------------------------------------------































    # TEA extensions pass this us the version of TEA they think they
    # are compatible with.
    TEA_VERSION="3.9"

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for correct TEA configuration" >&5
$as_echo_n "checking for correct TEA configuration... " >&6; }
    if test x"${PACKAGE_NAME}" = x ; then
	as_fn_error $? "
The PACKAGE_NAME variable must be defined by your TEA configure.in" "$LINENO" 5
    fi
    if test x"3.9" = x ; then
	as_fn_error $? "
TEA version not specified." "$LINENO" 5
    elif test "3.9" != "${TEA_VERSION}" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&5
$as_echo "warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&6; }
................................................................................









ac_aux_dir=
for ac_dir in tclconfig "$srcdir"/tclconfig; do
  if test -f "$ac_dir/install-sh"; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install-sh -c"
    break
  elif test -f "$ac_dir/install.sh"; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install.sh -c"
    break
  elif test -f "$ac_dir/shtool"; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/shtool install -c"
    break
  fi
done
if test -z "$ac_aux_dir"; then
  as_fn_error $? "cannot find install-sh, install.sh, or shtool in tclconfig \"$srcdir\"/tclconfig" "$LINENO" 5
fi

# These three variables are undocumented and unsupported,
# and are intended to be withdrawn in a future Autoconf release.
# They can cause serious problems if a builder's source tree is in a directory
# whose full name contains unusual characters.
ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.



#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------


................................................................................
	fi
	PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
    done



#--------------------------------------------------------------------

#




# You can add more files to clean if your extension creates any extra

# files by extending CLEANFILES.
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#
# A few miscellaneous platform-specific items:
# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------



#CLEANFILES="$CLEANFILES pkgIndex.tcl"

#--------------------------------------------------------------------
# Choose which headers you need.  Extension authors should try very
# hard to only rely on the Tcl public header files.  Internal headers
# contain private data structures and are subject to change without
# notice.
................................................................................
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi




Changes to configure.ac.

1
2
3
4
5
6
7
8
9
10
11
12
..
15
16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130



131

132
133
134
135
136
137
138
139
140
141
142
143
...
206
207
208
209
210
211
212
213
214
215
216
217
#!/bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.
#
#-----------------------------------------------------------------------
# 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.
#-----------------------------------------------------------------------
................................................................................

#--------------------------------------------------------------------
# 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.
#--------------------------------------------------------------------

AC_CONFIG_AUX_DIR(tclconfig)
TEA_INIT([3.9])



#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------

TEA_PATH_TCLCONFIG
TEA_LOAD_TCLCONFIG
................................................................................
    TEA_ADD_LIBS([${tdbc_STUB_LIB_SPEC}])
fi
TEA_ADD_CFLAGS([${tdbc_CFLAGS}])
TEA_ADD_STUB_SOURCES()
TEA_ADD_TCL_SOURCES([library/tdbcmysql.tcl])

#--------------------------------------------------------------------
# A few miscellaneous platform-specific items:
#
# Define a special symbol for Windows (BUILD_sample in this case) so
# that we create the export library with the dll.
#
# Windows creates a few extra files that need to be cleaned up.
# You can add more files to clean if your extension creates any extra
# files.



#

# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------

# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#CLEANFILES="$CLEANFILES pkgIndex.tcl"

#--------------------------------------------------------------------
# Choose which headers you need.  Extension authors should try very
# hard to only rely on the Tcl public header files.  Internal headers
# contain private data structures and are subject to change without
# notice.
................................................................................
# You may alternatively have a special pkgIndex.tcl.in or other files
# which require substituting th AC variables in.  Include these here.
#--------------------------------------------------------------------

CONFIGURE_OUTPUTS="Makefile pkgIndex.tcl config.cache config.log config.status"
AC_SUBST(CONFIGURE_OUTPUTS)

AC_CONFIG_FILES([Makefile pkgIndex.tcl])
AC_OUTPUT

# This is a comment added to force the 'execute' permission to update 
# in the Fossil repository.



|







 







<

>
>







 







<

<
<
<
<

<
>
>
>

>



<
<







 







|
<
<
<
<
1
2
3
4
5
6
7
8
9
10
11
12
..
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
...
117
118
119
120
121
122
123

124




125

126
127
128
129
130
131
132
133


134
135
136
137
138
139
140
...
203
204
205
206
207
208
209
210




#!/bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.

#-----------------------------------------------------------------------
# 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.
#-----------------------------------------------------------------------
................................................................................

#--------------------------------------------------------------------
# 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.
#--------------------------------------------------------------------


TEA_INIT([3.9])

AC_CONFIG_AUX_DIR(tclconfig)

#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------

TEA_PATH_TCLCONFIG
TEA_LOAD_TCLCONFIG
................................................................................
    TEA_ADD_LIBS([${tdbc_STUB_LIB_SPEC}])
fi
TEA_ADD_CFLAGS([${tdbc_CFLAGS}])
TEA_ADD_STUB_SOURCES()
TEA_ADD_TCL_SOURCES([library/tdbcmysql.tcl])

#--------------------------------------------------------------------

#




# You can add more files to clean if your extension creates any extra

# files by extending CLEANFILES.
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#
# A few miscellaneous platform-specific items:
# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------



#CLEANFILES="$CLEANFILES pkgIndex.tcl"

#--------------------------------------------------------------------
# Choose which headers you need.  Extension authors should try very
# hard to only rely on the Tcl public header files.  Internal headers
# contain private data structures and are subject to change without
# notice.
................................................................................
# You may alternatively have a special pkgIndex.tcl.in or other files
# which require substituting th AC variables in.  Include these here.
#--------------------------------------------------------------------

CONFIGURE_OUTPUTS="Makefile pkgIndex.tcl config.cache config.log config.status"
AC_SUBST(CONFIGURE_OUTPUTS)

AC_OUTPUT([Makefile pkgIndex.tcl])




Changes to doc/tdbc_mysql.n.

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
.PP
The \fBtdbc::mysql::connection create\fR object command supports the
\fB-encoding\fR, \fB-isolation\fR, \fB-readonly\fR and \fB-timeout\fR
options common to all TDBC drivers. The \fB-encoding\fR option will
always fail unless the encoding is \fButf-8\fR; the database connection
always uses UTF-8 encoding to be able to transfer arbitrary Unicode
characters. The \fB-readonly\fR option must be \fB0\fR, because
MySQL does not offer read-only connections. 
.PP
In addition, the following options are recognized:
.IP "\fB-host\fR \fIhostname\fR"
Connects to the host specified by \fIhostname\fR. This option must be
set on the initial creation of the connection; it cannot be changed
after connecting. Default is to connect to the local host.
.IP "\fB-port\fR \fInumber\fR"
................................................................................
pipe specified by \fIpath\fR . This option may not be changed after connecting.
It is used only when \fI-host\fR is not specified or is \fBlocalhost\fR.
.IP "\fB-user\fR \fIname\fR"
Presents \fIname\fR as the user name to the MySQL server. Default is the
current user ID.
.IP "\fB-passwd\fR \fIpassword\fR"
.IP "\fB-password\fR \fIpassword\fR"
These two options are synonymous. They present the given \fIpassword\fR as 
the user's password to the MySQL server. Default is not to present a password.
.IP "\fB-database\fR \fIname\fR"
.IP "\fB-db\fR \fIname\fR"
These two options are synonymous.  They present the given \fIname\fR as the
name of the default database to use in MySQL queries. If not specified,
the default database for the current user is used.
.IP "\fB-interactive\fR \fIflag\fR"






|







 







|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
.PP
The \fBtdbc::mysql::connection create\fR object command supports the
\fB-encoding\fR, \fB-isolation\fR, \fB-readonly\fR and \fB-timeout\fR
options common to all TDBC drivers. The \fB-encoding\fR option will
always fail unless the encoding is \fButf-8\fR; the database connection
always uses UTF-8 encoding to be able to transfer arbitrary Unicode
characters. The \fB-readonly\fR option must be \fB0\fR, because
MySQL does not offer read-only connections.
.PP
In addition, the following options are recognized:
.IP "\fB-host\fR \fIhostname\fR"
Connects to the host specified by \fIhostname\fR. This option must be
set on the initial creation of the connection; it cannot be changed
after connecting. Default is to connect to the local host.
.IP "\fB-port\fR \fInumber\fR"
................................................................................
pipe specified by \fIpath\fR . This option may not be changed after connecting.
It is used only when \fI-host\fR is not specified or is \fBlocalhost\fR.
.IP "\fB-user\fR \fIname\fR"
Presents \fIname\fR as the user name to the MySQL server. Default is the
current user ID.
.IP "\fB-passwd\fR \fIpassword\fR"
.IP "\fB-password\fR \fIpassword\fR"
These two options are synonymous. They present the given \fIpassword\fR as
the user's password to the MySQL server. Default is not to present a password.
.IP "\fB-database\fR \fIname\fR"
.IP "\fB-db\fR \fIname\fR"
These two options are synonymous.  They present the given \fIname\fR as the
name of the default database to use in MySQL queries. If not specified,
the default database for the current user is used.
.IP "\fB-interactive\fR \fIflag\fR"

Changes to generic/fakemysql.h.

175
176
177
178
179
180
181
182
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
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
    my_bool unused0;
    my_bool unused;
    my_bool compress;
    my_bool unused1;
#endif
    unsigned char *query_cache_query;
    unsigned int last_errno;
    unsigned char error; 
    my_bool unused2;
    my_bool return_errno;
    char last_error[MYSQL_ERRMSG_SIZE];
    char sqlstate[SQLSTATE_LENGTH+1];
    void *extension;
#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
    my_bool skip_big_packet;
#endif
};

/*
 * st_mysql differs between 5.0 and 5.1, but the 5.0 version is a
 * strict subset, we don't use any of the 5.1 fields, and we don't
 * ever allocate the structure ourselves. 
 */

struct st_mysql {
    NET net;
    unsigned char *connector_fd;
    char *host;
    char *user;
    char *passwd;
    char *unix_socket;
    char *server_version;
    char *host_info;
    char *info; 
    char *db;
    struct charset_info_st *charset;
    MYSQL_FIELD *fields;
    MEM_ROOT field_alloc;
    my_ulonglong affected_rows;
    my_ulonglong insert_id;
    my_ulonglong extra_info;
................................................................................
    LIST  *stmts;
    const struct st_mysql_methods *methods;
    void *thd;
    my_bool *unbuffered_fetch_owner;
    char *info_buffer;
};

/* 
 * There are different version of the MYSQL_BIND structure before and after
 * MySQL 5.1. We go after the fields of the structure using accessor functions
 * so that the code in this file is compatible with both versions.
 */

struct st_mysql_bind_51 {	/* Post-5.1 */
    unsigned long* length;
................................................................................
    my_bool long_data_used;
    my_bool is_null_value;
    void (*store_param_func)(NET* net, MYSQL_BIND* param);
    void (*fetch_result)(MYSQL_BIND*, MYSQL_FIELD*, unsigned char**);
    void (*skip_result)(MYSQL_BIND*, MYSQL_FIELD*, unsigned char**);
};

/* 
 * There are also different versions of the MYSQL_FIELD structure; fortunately,
 * the 5.1 version is a strict extension of the 5.0 version.
 */

struct st_mysql_field {
    char* name;
    char *org_name;






|













|











|







 







|







 







|







175
176
177
178
179
180
181
182
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
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
    my_bool unused0;
    my_bool unused;
    my_bool compress;
    my_bool unused1;
#endif
    unsigned char *query_cache_query;
    unsigned int last_errno;
    unsigned char error;
    my_bool unused2;
    my_bool return_errno;
    char last_error[MYSQL_ERRMSG_SIZE];
    char sqlstate[SQLSTATE_LENGTH+1];
    void *extension;
#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
    my_bool skip_big_packet;
#endif
};

/*
 * st_mysql differs between 5.0 and 5.1, but the 5.0 version is a
 * strict subset, we don't use any of the 5.1 fields, and we don't
 * ever allocate the structure ourselves.
 */

struct st_mysql {
    NET net;
    unsigned char *connector_fd;
    char *host;
    char *user;
    char *passwd;
    char *unix_socket;
    char *server_version;
    char *host_info;
    char *info;
    char *db;
    struct charset_info_st *charset;
    MYSQL_FIELD *fields;
    MEM_ROOT field_alloc;
    my_ulonglong affected_rows;
    my_ulonglong insert_id;
    my_ulonglong extra_info;
................................................................................
    LIST  *stmts;
    const struct st_mysql_methods *methods;
    void *thd;
    my_bool *unbuffered_fetch_owner;
    char *info_buffer;
};

/*
 * There are different version of the MYSQL_BIND structure before and after
 * MySQL 5.1. We go after the fields of the structure using accessor functions
 * so that the code in this file is compatible with both versions.
 */

struct st_mysql_bind_51 {	/* Post-5.1 */
    unsigned long* length;
................................................................................
    my_bool long_data_used;
    my_bool is_null_value;
    void (*store_param_func)(NET* net, MYSQL_BIND* param);
    void (*fetch_result)(MYSQL_BIND*, MYSQL_FIELD*, unsigned char**);
    void (*skip_result)(MYSQL_BIND*, MYSQL_FIELD*, unsigned char**);
};

/*
 * There are also different versions of the MYSQL_FIELD structure; fortunately,
 * the 5.1 version is a strict extension of the 5.0 version.
 */

struct st_mysql_field {
    char* name;
    char *org_name;

Changes to generic/mysqlStubDefs.txt.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# that the material in this file is not subject to copyright, under the
# doctrines of scenes a faire and of the merger of idea and expression.
# Accordingly, this file is in the public domain.
#
#-----------------------------------------------------------------------------

* STUBSTRUCT: mysqlStubs
* LIBRARY: libmysqlclient_r libmysqlclient libmysql 
* CONVENTION: STDCALL

int mysql_server_init(int, char**, char**);
void mysql_server_end(void);
my_ulonglong mysql_affected_rows(MYSQL*);
my_bool mysql_autocommit(MYSQL*, my_bool);
my_bool mysql_change_user(MYSQL*, const char*, const char*, const char*);






|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# that the material in this file is not subject to copyright, under the
# doctrines of scenes a faire and of the merger of idea and expression.
# Accordingly, this file is in the public domain.
#
#-----------------------------------------------------------------------------

* STUBSTRUCT: mysqlStubs
* LIBRARY: mysqlclient_r mysqlclient mysql
* CONVENTION: STDCALL

int mysql_server_init(int, char**, char**);
void mysql_server_end(void);
my_ulonglong mysql_affected_rows(MYSQL*);
my_bool mysql_autocommit(MYSQL*, my_bool);
my_bool mysql_change_user(MYSQL*, const char*, const char*, const char*);

Changes to generic/mysqlStubInit.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
..
24
25
26
27
28
29
30






31
32
33
34
35
36
37
38
39
40
41
...
131
132
133
134
135
136
137
138





139

140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * mysqlStubInit.c --
 *
 *	Stubs tables for the foreign MySQL libraries so that
 *	Tcl extensions can use them without the linker's knowing about them.
 *
 * @[email protected] 2010-12-27 19:26:47Z by genExtStubs.tcl from ../generic/mysqlStubDefs.txt
 *
 * Copyright (c) 2010 by Kevin B. Kenny.
 *
 * Please refer to the file, 'license.terms' for the conditions on
 * redistribution of this file and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *-----------------------------------------------------------------------------
................................................................................
/*
 * Static data used in this file
 */

/*
 * Names of the libraries that might contain the MySQL API
 */







static const char *const mysqlStubLibNames[] = {
    /* @[email protected]: DO NOT EDIT THESE NAMES */
    "libmysqlclient_r", "libmysqlclient", "libmysql", NULL
    /* @[email protected] */
};

/* ABI Version numbers of the MySQL API that we can cope with */

static const char *const mysqlSuffixes[] = {
    "", ".18", ".17", ".16", ".15", NULL
................................................................................
    Tcl_IncrRefCount(shlibext);

    /* Walk the list of possible library names to find an MySQL client */

    status = TCL_ERROR;
    for (i = 0; status == TCL_ERROR && mysqlStubLibNames[i] != NULL; ++i) {
	for (j = 0; status == TCL_ERROR && mysqlSuffixes[j] != NULL; ++j) {
	    path = Tcl_NewStringObj(mysqlStubLibNames[i], -1);





	    Tcl_AppendObjToObj(path, shlibext);

	    Tcl_AppendToObj(path, mysqlSuffixes[j], -1);

	    Tcl_IncrRefCount(path);
	
	    /* Try to load a client library and resolve symbols within it. */

	    Tcl_ResetResult(interp);
	    status = Tcl_LoadFile(interp, path, mysqlSymbolNames, 0,
				  (void*)mysqlStubs, &handle);
	    Tcl_DecrRefCount(path);
	}
    }

    /* 
     * Either we've successfully loaded a library (status == TCL_OK), 
     * or we've run out of library names (in which case status==TCL_ERROR
     * and the error message reflects the last unsuccessful load attempt).
     */
    Tcl_DecrRefCount(shlibext);
    if (status != TCL_OK) {
	return NULL;
    }
    return handle;
}





|







 







>
>
>
>
>
>



|







 







|
>
>
>
>
>

>

>

|









|
|









1
2
3
4
5
6
7
8
9
10
11
12
13
14
..
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
 * mysqlStubInit.c --
 *
 *	Stubs tables for the foreign MySQL libraries so that
 *	Tcl extensions can use them without the linker's knowing about them.
 *
 * @[email protected] 2015-06-26 08:46:10Z by genExtStubs.tcl from ../generic/mysqlStubDefs.txt
 *
 * Copyright (c) 2010 by Kevin B. Kenny.
 *
 * Please refer to the file, 'license.terms' for the conditions on
 * redistribution of this file and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *-----------------------------------------------------------------------------
................................................................................
/*
 * Static data used in this file
 */

/*
 * Names of the libraries that might contain the MySQL API
 */

#if defined(__CYGWIN__) && !defined(LIBPREFIX)
# define LIBPREFIX "cyg"
#else
# define LIBPREFIX "lib"
#endif

static const char *const mysqlStubLibNames[] = {
    /* @[email protected]: DO NOT EDIT THESE NAMES */
    "mysqlclient_r", "mysqlclient", "mysql", NULL
    /* @[email protected] */
};

/* ABI Version numbers of the MySQL API that we can cope with */

static const char *const mysqlSuffixes[] = {
    "", ".18", ".17", ".16", ".15", NULL
................................................................................
    Tcl_IncrRefCount(shlibext);

    /* Walk the list of possible library names to find an MySQL client */

    status = TCL_ERROR;
    for (i = 0; status == TCL_ERROR && mysqlStubLibNames[i] != NULL; ++i) {
	for (j = 0; status == TCL_ERROR && mysqlSuffixes[j] != NULL; ++j) {
	    path = Tcl_NewStringObj(LIBPREFIX, -1);
	    Tcl_AppendToObj(path, mysqlStubLibNames[j], -1);
#ifdef __CYGWIN__
	    Tcl_AppendToObj(path, "-", -1);
	    Tcl_AppendToObj(path, mysqlSuffixes[j]+1, -1);
#endif
	    Tcl_AppendObjToObj(path, shlibext);
#ifndef __CYGWIN__
	    Tcl_AppendToObj(path, mysqlSuffixes[j], -1);
#endif
	    Tcl_IncrRefCount(path);

	    /* Try to load a client library and resolve symbols within it. */

	    Tcl_ResetResult(interp);
	    status = Tcl_LoadFile(interp, path, mysqlSymbolNames, 0,
				  (void*)mysqlStubs, &handle);
	    Tcl_DecrRefCount(path);
	}
    }

    /*
     * Either we've successfully loaded a library (status == TCL_OK),
     * or we've run out of library names (in which case status==TCL_ERROR
     * and the error message reflects the last unsuccessful load attempt).
     */
    Tcl_DecrRefCount(shlibext);
    if (status != TCL_OK) {
	return NULL;
    }
    return handle;
}

Changes to generic/mysqlStubs.h.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *-----------------------------------------------------------------------------
 *
 * ../generic/mysqlStubs.h --
 *
 *	Stubs for procedures in mysqlStubDefs.txt
 *
 * Generated by genExtStubs.tcl: DO NOT EDIT
 * 2010-12-27 19:26:47Z
 *
 *-----------------------------------------------------------------------------
 */

typedef struct mysqlStubDefs {

    /* Functions from libraries: libmysqlclient_r libmysqlclient libmysql */

    int (STDCALL*mysql_server_initPtr)(int, char**, char**);
    void (STDCALL*mysql_server_endPtr)(void);
    my_ulonglong (STDCALL*mysql_affected_rowsPtr)(MYSQL*);
    my_bool (STDCALL*mysql_autocommitPtr)(MYSQL*, my_bool);
    my_bool (STDCALL*mysql_change_userPtr)(MYSQL*, const char*, const char*, const char*);
    my_bool (STDCALL*mysql_closePtr)(MYSQL*);






|






|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *-----------------------------------------------------------------------------
 *
 * ../generic/mysqlStubs.h --
 *
 *	Stubs for procedures in mysqlStubDefs.txt
 *
 * Generated by genExtStubs.tcl: DO NOT EDIT
 * 2015-06-26 08:46:09Z
 *
 *-----------------------------------------------------------------------------
 */

typedef struct mysqlStubDefs {

    /* Functions from libraries: mysqlclient_r mysqlclient mysql */

    int (STDCALL*mysql_server_initPtr)(int, char**, char**);
    void (STDCALL*mysql_server_endPtr)(void);
    my_ulonglong (STDCALL*mysql_affected_rowsPtr)(MYSQL*);
    my_bool (STDCALL*mysql_autocommitPtr)(MYSQL*, my_bool);
    my_bool (STDCALL*mysql_change_userPtr)(MYSQL*, const char*, const char*, const char*);
    my_bool (STDCALL*mysql_closePtr)(MYSQL*);

Changes to generic/tdbcmysql.c.

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
....
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
....
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
....
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
....
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
....
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
....
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
....
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
....
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
....
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
....
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
....
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
....
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
....
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
....
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
....
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
....
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
....
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
....
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
....
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
....
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
....
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
....
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
....
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
    do {					\
	PerInterpData* _pidata = x;		\
	if ((--(_pidata->refCount)) <= 0) {	\
	    DeletePerInterpData(_pidata);	\
	}					\
    } while(0)

/* 
 * Structure that carries the data for an MYSQL connection
 *
 * 	The ConnectionData structure is refcounted to simplify the
 *	destruction of statements associated with a connection.
 *	When a connection is destroyed, the subordinate namespace that
 *	contains its statements is taken down, destroying them. It's
 *	not safe to take down the ConnectionData until nothing is
................................................................................
 */

typedef struct StatementData {
    int refCount;		/* Reference count */
    ConnectionData* cdata;	/* Data for the connection to which this
				 * statement pertains. */
    Tcl_Obj* subVars;	        /* List of variables to be substituted, in the
				 * order in which they appear in the 
				 * statement */
    struct ParamData *params;	/* Data types and attributes of parameters */
    Tcl_Obj* nativeSql;		/* Native SQL statement to pass into
				 * MySQL */
    MYSQL_STMT* stmtPtr;	/* MySQL statement handle */
    MYSQL_RES* metadataPtr;	/* MySQL result set metadata */
    Tcl_Obj* columnNames;	/* Column names in the result set */
................................................................................
				/* version */
    "paramtype",		/* name */
    StatementParamtypeMethod,	/* callProc */
    NULL,			/* deleteProc */
    NULL			/* cloneProc */
};

/* 
 * Methods to create on the statement class. 
 */

const static Tcl_MethodType* StatementMethods[] = {
    &StatementParamsMethodType,
    &StatementParamtypeMethodType,
    NULL
};
................................................................................
    if (mysqlClientVersion >= 50100) {
	return (MYSQL_BIND*)(((struct st_mysql_bind_51*) b) + i);
    } else {
	return (MYSQL_BIND*)(((struct st_mysql_bind_50*) b) + i);
    }
}
 
/* 
 *-----------------------------------------------------------------------------
 *
 * MysqlBindAllocBuffer --
 *
 *	Allocates the buffer in a MYSQL_BIND object
 *
 * Results:
................................................................................
    if (mysqlClientVersion >= 50100) {
	return ((struct st_mysql_bind_51*) b)[i].buffer_type;
    } else {
	return ((struct st_mysql_bind_50*) b)[i].buffer_type;
    }
}

static void 
MysqlBindSetBufferType(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    enum enum_field_types t	/* Buffer type to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].buffer_type = t;
    } else {
	((struct st_mysql_bind_50*) b)[i].buffer_type = t;
    }
}

static void 
MysqlBindSetLength(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    unsigned long* p		/* Length pointer to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].length = p;
    } else {
	((struct st_mysql_bind_50*) b)[i].length = p;
    }
}

static void 
MysqlBindSetIsNull(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    my_bool* p			/* "Is null" indicator pointer to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].is_null = p;
    } else {
	((struct st_mysql_bind_50*) b)[i].is_null = p;
    }
}

static void 
MysqlBindSetError(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    my_bool* p			/* Error indicator pointer to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].error = p;
................................................................................

	if (cdata->mysqlPtr != NULL && !(ConnOptions[optionIndex].flags
					 & CONN_OPT_FLAG_MOD)) {
	    Tcl_Obj* msg = Tcl_NewStringObj("\"", -1);
	    Tcl_AppendObjToObj(msg, objv[i]);
	    Tcl_AppendToObj(msg, "\" option cannot be changed dynamically", -1);
	    Tcl_SetObjResult(interp, msg);
	    Tcl_SetErrorCode(interp, "TDBC", "GENERAL_ERROR", "HY000", 
			     "MYSQL", "-1", NULL);
	    return TCL_ERROR;
	}

	/* Record option value */

	switch (ConnOptions[optionIndex].type) {
................................................................................

	/* Configuring a new connection. Open the database */

	cdata->mysqlPtr = mysql_init(NULL);
	if (cdata->mysqlPtr == NULL) {
	    Tcl_SetObjResult(interp,
			     Tcl_NewStringObj("mysql_init() failed.", -1));
	    Tcl_SetErrorCode(interp, "TDBC", "GENERAL_ERROR", "HY001", 
			     "MYSQL", "NULL", NULL);
	    return TCL_ERROR;
	}

	/* Set character set for the connection */

	mysql_options(cdata->mysqlPtr, MYSQL_SET_CHARSET_NAME, "utf8");
	
	    /* Set SSL options if needed */

	if (sslFlag) {
	    mysql_ssl_set(cdata->mysqlPtr, stringOpts[INDX_SSLKEY],
			  stringOpts[INDX_SSLCERT], stringOpts[INDX_SSLCA],
			  stringOpts[INDX_SSLCAPATH],
			  stringOpts[INDX_SSLCIPHER]);
	}
	
	/* Establish the connection */
	
	/*
	 * TODO - mutex around this unless linked to libmysqlclient_r ?
	 */
	
	if (mysql_real_connect(cdata->mysqlPtr, stringOpts[INDX_HOST],
			       stringOpts[INDX_USER], stringOpts[INDX_PASSWD],
			       stringOpts[INDX_DB], port,
			       stringOpts[INDX_SOCKET], mysqlFlags) == NULL) {
	    TransferMysqlError(interp, cdata->mysqlPtr);
	    return TCL_ERROR;
	}

	cdata->flags |= CONN_FLAG_AUTOCOMMIT;
	
    } else {

	/* Already open connection */

	if (stringOpts[INDX_USER] != NULL) {

	    /* User name changed - log in again */

	    if (mysql_change_user(cdata->mysqlPtr, 
				  stringOpts[INDX_USER],
				  stringOpts[INDX_PASSWD],
				  stringOpts[INDX_DB])) {
		TransferMysqlError(interp, cdata->mysqlPtr);
		return TCL_ERROR;
	    }
	} else if (stringOpts[INDX_DB] != NULL) {
................................................................................
    cdata->pidata = pidata;
    cdata->mysqlPtr = NULL;
    cdata->nCollations = 0;
    cdata->collationSizes = NULL;
    cdata->flags = 0;
    IncrPerInterpRefCount(pidata);
    Tcl_ObjectSetMetadata(thisObject, &connectionDataType, (ClientData) cdata);
    
    /* Configure the connection */

    if (ConfigureConnection(cdata, interp, objc, objv, skip) != TCL_OK) {
	return TCL_ERROR;
    }

    return TCL_OK;
................................................................................
 * ConnectionColumnsMethod --
 *
 *	Method that asks for the names of columns in a table
 *	in the database (optionally matching a given pattern)
 *
 * Usage:
 * 	$connection columns table ?pattern?
 * 
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns the list of tables
 *
 *-----------------------------------------------------------------------------
................................................................................
	    if (IS_NUM(field->type)) {
		Tcl_DictObjPut(NULL, attrs, literals[LIT_PRECISION],
			       Tcl_NewIntObj(field->length));
	    } else if (field->charsetnr < cdata->nCollations) {
		Tcl_DictObjPut(NULL, attrs, literals[LIT_PRECISION],
		    Tcl_NewIntObj(field->length
			/ cdata->collationSizes[field->charsetnr]));
	    }		
	    Tcl_DictObjPut(NULL, attrs, literals[LIT_SCALE],
			   Tcl_NewIntObj(field->decimals));
	    Tcl_DictObjPut(NULL, attrs, literals[LIT_NULLABLE],
			   Tcl_NewIntObj(!(field->flags 
					   & (NOT_NULL_FLAG))));
	    Tcl_DictObjPut(NULL, retval, name, attrs);
	}
	mysql_free_result(results);
	Tcl_SetObjResult(interp, retval);
	Tcl_DecrRefCount(retval);
	return TCL_OK;
................................................................................
 * ConnectionCommitMethod --
 *
 *	Method that requests that a pending transaction against a database
 * 	be committed.
 *
 * Usage:
 *	$connection commit
 * 
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns an empty Tcl result if successful, and throws an error
 *	otherwise.
 *
................................................................................
 *	Other options supported by the constructor are here in read-only
 *	mode; any attempt to change them will result in an error.
 *
 *-----------------------------------------------------------------------------
 */

static int ConnectionConfigureMethod(
     ClientData clientData, 
     Tcl_Interp* interp,
     Tcl_ObjectContext objectContext,
     int objc, 
     Tcl_Obj *const objv[]
) {
    Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext);
				/* The current connection object */
    int skip = Tcl_ObjectContextSkippedArgs(objectContext);
				/* Number of arguments to skip */
    ConnectionData* cdata = (ConnectionData*)
................................................................................

    /* Execute the given statement */

    if (mysql_query(cdata->mysqlPtr, Tcl_GetString(objv[2]))) {
	TransferMysqlError(interp, cdata->mysqlPtr);
	return TCL_ERROR;
    }
    
    /* Retrieve the result set */

    resultPtr = mysql_store_result(cdata->mysqlPtr);
    nColumns = mysql_field_count(cdata->mysqlPtr);
    if (resultPtr == NULL) {
	/* 
	 * Can't retrieve result set. Distinguish result-less statements
	 * from MySQL errors.
	 */
	if (nColumns == 0) {
	    Tcl_SetObjResult
		(interp,
		 Tcl_NewWideIntObj(mysql_affected_rows(cdata->mysqlPtr)));
................................................................................
 * ConnectionRollbackMethod --
 *
 *	Method that requests that a pending transaction against a database
 * 	be rolled back.
 *
 * Usage:
 * 	$connection rollback
 * 
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns an empty Tcl result if successful, and throws an error
 *	otherwise.
 *
................................................................................
 * Results:
 *	None.
 *
 * The [$connection columns $table] method needs to know the sizes
 * of characters in a given column's collation and character set.
 * This information is available by querying INFORMATION_SCHEMA, which
 * is easier to do from Tcl than C. This method passes in the results.
 * 
 *-----------------------------------------------------------------------------
 */

static int
ConnectionSetCollationInfoMethod(
    ClientData clientData,	/* Completion type */
    Tcl_Interp* interp,		/* Tcl interpreter */
................................................................................
 * ConnectionTablesMethod --
 *
 *	Method that asks for the names of tables in the database (optionally
 *	matching a given pattern
 *
 * Usage:
 * 	$connection tables ?pattern?
 * 
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns the list of tables
 *
 *-----------------------------------------------------------------------------
................................................................................
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * DeleteConnectionMetadata, DeleteConnection --
 *
 *	Cleans up when a database connection is deleted.  
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Terminates the connection and frees all system resources associated
 *	with it.
................................................................................
     */

    if (stmtPtr == NULL) {
	TransferMysqlError(interp, cdata->mysqlPtr);
    } else {

	/* Prepare the statement */
	
	nativeSqlStr = Tcl_GetStringFromObj(sdata->nativeSql, &nativeSqlLen);
	if (mysql_stmt_prepare(stmtPtr, nativeSqlStr, nativeSqlLen)) {
	    TransferMysqlStmtError(interp, stmtPtr);
	    mysql_stmt_close(stmtPtr);
	    stmtPtr = NULL;
	}
    }
................................................................................
    if (Tcl_ListObjGetElements(interp, tokens, &tokenc, &tokenv) != TCL_OK) {
	goto freeTokens;
    }
    nativeSql = Tcl_NewObj();
    Tcl_IncrRefCount(nativeSql);
    for (i = 0; i < tokenc; ++i) {
	tokenStr = Tcl_GetStringFromObj(tokenv[i], &tokenLen);
	
	switch (tokenStr[0]) {
	case '$':
	case ':':
	case '@':
	    Tcl_AppendToObj(nativeSql, "?", 1);
	    Tcl_ListObjAppendElement(NULL, sdata->subVars, 
				     Tcl_NewStringObj(tokenStr+1, tokenLen-1));
	    break;

	case ';':
	    Tcl_SetObjResult(interp,
			     Tcl_NewStringObj("tdbc::mysql"
					      " does not support semicolons "
					      "in statements", -1));
	    goto freeNativeSql;
	    break; 

	default:
	    Tcl_AppendToObj(nativeSql, tokenStr, tokenLen);
	    break;

	}
    }
................................................................................
    Tcl_ListObjLength(NULL, sdata->subVars, &nParams);
    for (i = 0; i < nParams; ++i) {
	paramDesc = Tcl_NewObj();
	Tcl_ListObjIndex(NULL, sdata->subVars, i, &paramName);
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_NAME], paramName);
	switch (sdata->params[i].flags & (PARAM_IN | PARAM_OUT)) {
	case PARAM_IN:
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_DIRECTION], 
			   literals[LIT_IN]);
	    break;
	case PARAM_OUT:
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_DIRECTION], 
			   literals[LIT_OUT]);
	    break;
	case PARAM_IN | PARAM_OUT:
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_DIRECTION], 
			   literals[LIT_INOUT]);
	    break;
	default:
	    break;
	}
	typeHashEntry =
	    Tcl_FindHashEntry(&(pidata->typeNumHash),
................................................................................
	}
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_PRECISION],
		       Tcl_NewIntObj(sdata->params[i].precision));
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_SCALE],
		       Tcl_NewIntObj(sdata->params[i].scale));
	Tcl_DictObjPut(NULL, retVal, paramName, paramDesc);
    }
	
    Tcl_SetObjResult(interp, retVal);
    return TCL_OK;
}
 
/*
 *-----------------------------------------------------------------------------
 *
................................................................................
    int i;

    /* Check parameters */

    if (objc < 4) {
	goto wrongNumArgs;
    }
    
    i = 3;
    if (Tcl_GetIndexFromObjStruct(interp, objv[i], directions, 
				  sizeof(directions[0]), "direction",
				  TCL_EXACT, &direction) != TCL_OK) {
	direction = PARAM_IN;
	Tcl_ResetResult(interp);
    } else {
	++i;
    }
................................................................................
    Tcl_Obj* paramValObj;	/* Value of the current parameter */
    const char* paramValStr;	/* String value of the current parameter */
    char* bufPtr;		/* Pointer to the parameter buffer */
    int len;			/* Length of a bound parameter */
    int nColumns;		/* Number of columns in the result set */
    MYSQL_FIELD* fields = NULL;	/* Description of columns of the result set */
    MYSQL_BIND* resultBindings;	/* Bindings of the columns of the result set */
    unsigned long* resultLengths; 
				/* Lengths of the columns of the result set */
    int i;

    /* Check parameter count */

    if (objc != skip+1 && objc != skip+2) {
	Tcl_WrongNumArgs(interp, skip, objv, "statement ?dictionary?");
................................................................................
	Tcl_AppendResult(interp, Tcl_GetString(objv[skip]),
			 " does not refer to a MySQL statement", NULL);
	return TCL_ERROR;
    }
    Tcl_ListObjLength(NULL, sdata->columnNames, &nColumns);
    cdata = sdata->cdata;

    /* 
     * If there is no transaction in progress, turn on auto-commit so that
     * this statement will execute directly.
     */

    if ((cdata->flags & (CONN_FLAG_IN_XCN | CONN_FLAG_AUTOCOMMIT)) == 0) {
	if (mysql_autocommit(cdata->mysqlPtr, 1)) {
	    TransferMysqlError(interp, cdata->mysqlPtr);
................................................................................
			       paramNameObj, &paramValObj) != TCL_OK) {
		return TCL_ERROR;
	    }
	} else {

	    /* Param from a variable */

	    paramValObj = Tcl_GetVar2Ex(interp, paramName, NULL, 
					TCL_LEAVE_ERR_MSG);
	}

	/* 
	 * At this point, paramValObj contains the parameter to bind.
	 * Convert the parameters to the appropriate data types for
	 * MySQL's prepared statement interface, and bind them.
	 */

	if (paramValObj != NULL) {
	    switch (sdata->params[nBound].dataType & 0xffff) {
................................................................................
					   MYSQL_TYPE_BLOB);
		    paramValStr = (char*)
			Tcl_GetByteArrayFromObj(paramValObj, &len);
		} else {
		    MysqlBindSetBufferType(rdata->paramBindings, nBound,
					   MYSQL_TYPE_STRING);
		    paramValStr = Tcl_GetStringFromObj(paramValObj, &len);
		}		    
		bufPtr = MysqlBindAllocBuffer(rdata->paramBindings, nBound,
					      len+1);
		memcpy(bufPtr, paramValStr, len);
		rdata->paramLengths[nBound] = len;
		MysqlBindSetLength(rdata->paramBindings, nBound,
				   &(rdata->paramLengths[nBound]));
		break; 

	    }
	} else {
	    MysqlBindSetBufferType(rdata->paramBindings, nBound,
				   MYSQL_TYPE_NULL);
	}
    }

    /* Execute the statement */
    
    /* 
     * It is tempting to conserve client memory here by omitting
     * the call to 'mysql_stmt_store_result', but doing so causes
     * 'calls out of sync' errors when attempting to prepare a
     * statement while a result set is open. Certain of these errors
     * can, in turn, be avoided by using mysql_stmt_set_attr
     * and turning on "CURSOR_MODE_READONLY", but that, in turn
     * causes the server summarily to disconnect the client in
................................................................................
				/* Per interpreter data */
    Tcl_Obj** literals = pidata->literals;
				/* Literal pool */

    int nColumns = 0;		/* Number of columns in the result set */
    Tcl_Obj* colName;		/* Name of the current column */
    Tcl_Obj* resultRow;		/* Row of the result set under construction */
    
    Tcl_Obj* colObj;		/* Column obtained from the row */
    int status = TCL_ERROR;	/* Status return from this command */
    MYSQL_FIELD* fields;	/* Fields of the result set */
    MYSQL_BIND* resultBindings = rdata->resultBindings;
				/* Descriptions of the results */
    unsigned long* resultLengths = rdata->resultLengths;
				/* String lengths of the results */
................................................................................
	MYSQL_FIELD* field = MysqlFieldIndex(fields, i);
	colObj = NULL;
	if (!resultNulls[i]) {
	    if (resultLengths[i]
		> MysqlBindGetBufferLength(resultBindings, i)) {
		MysqlBindFreeBuffer(resultBindings, i);
		MysqlBindAllocBuffer(resultBindings, i, resultLengths[i] + 1);
		if (mysql_stmt_fetch_column(rdata->stmtPtr, 
					    MysqlBindIndex(resultBindings, i),
					    i, 0)) {
		    goto cleanup;
		}
	    }
	    bufPtr = MysqlBindGetBuffer(resultBindings, i);
	    switch (MysqlBindGetBufferType(resultBindings, i)) {
................................................................................

    /* Provide the current package */

    if (Tcl_PkgProvide(interp, "tdbc::mysql", PACKAGE_VERSION) == TCL_ERROR) {
	return TCL_ERROR;
    }

    /* 
     * Create per-interpreter data for the package
     */

    pidata = (PerInterpData*) ckalloc(sizeof(PerInterpData));
    pidata->refCount = 1;
    for (i = 0; i < LIT__END; ++i) {
	pidata->literals[i] = Tcl_NewStringObj(LiteralValues[i], -1);
	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].num),
				&new);
	Tcl_Obj* nameObj = Tcl_NewStringObj(dataTypes[i].name, -1);
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(entry, (ClientData) nameObj);
    }

    /* 
     * Find the connection class, and attach an 'init' method to it.
     */

    nameObj = Tcl_NewStringObj("::tdbc::mysql::connection", -1);
    Tcl_IncrRefCount(nameObj);
    if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
	Tcl_DecrRefCount(nameObj);






|







 







|







 







|
|







 







|







 







|












|












|












|







 







|







 







|







|








|

|



|









|








|







 







|







 







|







 







|



|







 







|







 







|


|







 







|





|







 







|







 







|







 







|







 







|







 







|







 







|





|









|







 







|



|



|







 







|







 







|

|







 







|







 







|







 







|



|







 







|






|









|
|







 







|







 







|







 







|













|







|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
....
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
....
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
....
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
....
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
....
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
....
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
....
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
....
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
....
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
....
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
....
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
....
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
....
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
....
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
....
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
....
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
....
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
....
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
....
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
....
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
....
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
....
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
....
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
    do {					\
	PerInterpData* _pidata = x;		\
	if ((--(_pidata->refCount)) <= 0) {	\
	    DeletePerInterpData(_pidata);	\
	}					\
    } while(0)

/*
 * Structure that carries the data for an MYSQL connection
 *
 * 	The ConnectionData structure is refcounted to simplify the
 *	destruction of statements associated with a connection.
 *	When a connection is destroyed, the subordinate namespace that
 *	contains its statements is taken down, destroying them. It's
 *	not safe to take down the ConnectionData until nothing is
................................................................................
 */

typedef struct StatementData {
    int refCount;		/* Reference count */
    ConnectionData* cdata;	/* Data for the connection to which this
				 * statement pertains. */
    Tcl_Obj* subVars;	        /* List of variables to be substituted, in the
				 * order in which they appear in the
				 * statement */
    struct ParamData *params;	/* Data types and attributes of parameters */
    Tcl_Obj* nativeSql;		/* Native SQL statement to pass into
				 * MySQL */
    MYSQL_STMT* stmtPtr;	/* MySQL statement handle */
    MYSQL_RES* metadataPtr;	/* MySQL result set metadata */
    Tcl_Obj* columnNames;	/* Column names in the result set */
................................................................................
				/* version */
    "paramtype",		/* name */
    StatementParamtypeMethod,	/* callProc */
    NULL,			/* deleteProc */
    NULL			/* cloneProc */
};

/*
 * Methods to create on the statement class.
 */

const static Tcl_MethodType* StatementMethods[] = {
    &StatementParamsMethodType,
    &StatementParamtypeMethodType,
    NULL
};
................................................................................
    if (mysqlClientVersion >= 50100) {
	return (MYSQL_BIND*)(((struct st_mysql_bind_51*) b) + i);
    } else {
	return (MYSQL_BIND*)(((struct st_mysql_bind_50*) b) + i);
    }
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * MysqlBindAllocBuffer --
 *
 *	Allocates the buffer in a MYSQL_BIND object
 *
 * Results:
................................................................................
    if (mysqlClientVersion >= 50100) {
	return ((struct st_mysql_bind_51*) b)[i].buffer_type;
    } else {
	return ((struct st_mysql_bind_50*) b)[i].buffer_type;
    }
}

static void
MysqlBindSetBufferType(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    enum enum_field_types t	/* Buffer type to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].buffer_type = t;
    } else {
	((struct st_mysql_bind_50*) b)[i].buffer_type = t;
    }
}

static void
MysqlBindSetLength(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    unsigned long* p		/* Length pointer to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].length = p;
    } else {
	((struct st_mysql_bind_50*) b)[i].length = p;
    }
}

static void
MysqlBindSetIsNull(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    my_bool* p			/* "Is null" indicator pointer to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].is_null = p;
    } else {
	((struct st_mysql_bind_50*) b)[i].is_null = p;
    }
}

static void
MysqlBindSetError(
    MYSQL_BIND* b, 		/* Binding array to alter */
    int i,			/* Index in the binding array */
    my_bool* p			/* Error indicator pointer to assign */
) {
    if (mysqlClientVersion >= 50100) {
	((struct st_mysql_bind_51*) b)[i].error = p;
................................................................................

	if (cdata->mysqlPtr != NULL && !(ConnOptions[optionIndex].flags
					 & CONN_OPT_FLAG_MOD)) {
	    Tcl_Obj* msg = Tcl_NewStringObj("\"", -1);
	    Tcl_AppendObjToObj(msg, objv[i]);
	    Tcl_AppendToObj(msg, "\" option cannot be changed dynamically", -1);
	    Tcl_SetObjResult(interp, msg);
	    Tcl_SetErrorCode(interp, "TDBC", "GENERAL_ERROR", "HY000",
			     "MYSQL", "-1", NULL);
	    return TCL_ERROR;
	}

	/* Record option value */

	switch (ConnOptions[optionIndex].type) {
................................................................................

	/* Configuring a new connection. Open the database */

	cdata->mysqlPtr = mysql_init(NULL);
	if (cdata->mysqlPtr == NULL) {
	    Tcl_SetObjResult(interp,
			     Tcl_NewStringObj("mysql_init() failed.", -1));
	    Tcl_SetErrorCode(interp, "TDBC", "GENERAL_ERROR", "HY001",
			     "MYSQL", "NULL", NULL);
	    return TCL_ERROR;
	}

	/* Set character set for the connection */

	mysql_options(cdata->mysqlPtr, MYSQL_SET_CHARSET_NAME, "utf8");

	    /* Set SSL options if needed */

	if (sslFlag) {
	    mysql_ssl_set(cdata->mysqlPtr, stringOpts[INDX_SSLKEY],
			  stringOpts[INDX_SSLCERT], stringOpts[INDX_SSLCA],
			  stringOpts[INDX_SSLCAPATH],
			  stringOpts[INDX_SSLCIPHER]);
	}

	/* Establish the connection */

	/*
	 * TODO - mutex around this unless linked to libmysqlclient_r ?
	 */

	if (mysql_real_connect(cdata->mysqlPtr, stringOpts[INDX_HOST],
			       stringOpts[INDX_USER], stringOpts[INDX_PASSWD],
			       stringOpts[INDX_DB], port,
			       stringOpts[INDX_SOCKET], mysqlFlags) == NULL) {
	    TransferMysqlError(interp, cdata->mysqlPtr);
	    return TCL_ERROR;
	}

	cdata->flags |= CONN_FLAG_AUTOCOMMIT;

    } else {

	/* Already open connection */

	if (stringOpts[INDX_USER] != NULL) {

	    /* User name changed - log in again */

	    if (mysql_change_user(cdata->mysqlPtr,
				  stringOpts[INDX_USER],
				  stringOpts[INDX_PASSWD],
				  stringOpts[INDX_DB])) {
		TransferMysqlError(interp, cdata->mysqlPtr);
		return TCL_ERROR;
	    }
	} else if (stringOpts[INDX_DB] != NULL) {
................................................................................
    cdata->pidata = pidata;
    cdata->mysqlPtr = NULL;
    cdata->nCollations = 0;
    cdata->collationSizes = NULL;
    cdata->flags = 0;
    IncrPerInterpRefCount(pidata);
    Tcl_ObjectSetMetadata(thisObject, &connectionDataType, (ClientData) cdata);

    /* Configure the connection */

    if (ConfigureConnection(cdata, interp, objc, objv, skip) != TCL_OK) {
	return TCL_ERROR;
    }

    return TCL_OK;
................................................................................
 * ConnectionColumnsMethod --
 *
 *	Method that asks for the names of columns in a table
 *	in the database (optionally matching a given pattern)
 *
 * Usage:
 * 	$connection columns table ?pattern?
 *
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns the list of tables
 *
 *-----------------------------------------------------------------------------
................................................................................
	    if (IS_NUM(field->type)) {
		Tcl_DictObjPut(NULL, attrs, literals[LIT_PRECISION],
			       Tcl_NewIntObj(field->length));
	    } else if (field->charsetnr < cdata->nCollations) {
		Tcl_DictObjPut(NULL, attrs, literals[LIT_PRECISION],
		    Tcl_NewIntObj(field->length
			/ cdata->collationSizes[field->charsetnr]));
	    }
	    Tcl_DictObjPut(NULL, attrs, literals[LIT_SCALE],
			   Tcl_NewIntObj(field->decimals));
	    Tcl_DictObjPut(NULL, attrs, literals[LIT_NULLABLE],
			   Tcl_NewIntObj(!(field->flags
					   & (NOT_NULL_FLAG))));
	    Tcl_DictObjPut(NULL, retval, name, attrs);
	}
	mysql_free_result(results);
	Tcl_SetObjResult(interp, retval);
	Tcl_DecrRefCount(retval);
	return TCL_OK;
................................................................................
 * ConnectionCommitMethod --
 *
 *	Method that requests that a pending transaction against a database
 * 	be committed.
 *
 * Usage:
 *	$connection commit
 *
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns an empty Tcl result if successful, and throws an error
 *	otherwise.
 *
................................................................................
 *	Other options supported by the constructor are here in read-only
 *	mode; any attempt to change them will result in an error.
 *
 *-----------------------------------------------------------------------------
 */

static int ConnectionConfigureMethod(
     ClientData clientData,
     Tcl_Interp* interp,
     Tcl_ObjectContext objectContext,
     int objc,
     Tcl_Obj *const objv[]
) {
    Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext);
				/* The current connection object */
    int skip = Tcl_ObjectContextSkippedArgs(objectContext);
				/* Number of arguments to skip */
    ConnectionData* cdata = (ConnectionData*)
................................................................................

    /* Execute the given statement */

    if (mysql_query(cdata->mysqlPtr, Tcl_GetString(objv[2]))) {
	TransferMysqlError(interp, cdata->mysqlPtr);
	return TCL_ERROR;
    }

    /* Retrieve the result set */

    resultPtr = mysql_store_result(cdata->mysqlPtr);
    nColumns = mysql_field_count(cdata->mysqlPtr);
    if (resultPtr == NULL) {
	/*
	 * Can't retrieve result set. Distinguish result-less statements
	 * from MySQL errors.
	 */
	if (nColumns == 0) {
	    Tcl_SetObjResult
		(interp,
		 Tcl_NewWideIntObj(mysql_affected_rows(cdata->mysqlPtr)));
................................................................................
 * ConnectionRollbackMethod --
 *
 *	Method that requests that a pending transaction against a database
 * 	be rolled back.
 *
 * Usage:
 * 	$connection rollback
 *
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns an empty Tcl result if successful, and throws an error
 *	otherwise.
 *
................................................................................
 * Results:
 *	None.
 *
 * The [$connection columns $table] method needs to know the sizes
 * of characters in a given column's collation and character set.
 * This information is available by querying INFORMATION_SCHEMA, which
 * is easier to do from Tcl than C. This method passes in the results.
 *
 *-----------------------------------------------------------------------------
 */

static int
ConnectionSetCollationInfoMethod(
    ClientData clientData,	/* Completion type */
    Tcl_Interp* interp,		/* Tcl interpreter */
................................................................................
 * ConnectionTablesMethod --
 *
 *	Method that asks for the names of tables in the database (optionally
 *	matching a given pattern
 *
 * Usage:
 * 	$connection tables ?pattern?
 *
 * Parameters:
 *	None.
 *
 * Results:
 *	Returns the list of tables
 *
 *-----------------------------------------------------------------------------
................................................................................
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * DeleteConnectionMetadata, DeleteConnection --
 *
 *	Cleans up when a database connection is deleted.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Terminates the connection and frees all system resources associated
 *	with it.
................................................................................
     */

    if (stmtPtr == NULL) {
	TransferMysqlError(interp, cdata->mysqlPtr);
    } else {

	/* Prepare the statement */

	nativeSqlStr = Tcl_GetStringFromObj(sdata->nativeSql, &nativeSqlLen);
	if (mysql_stmt_prepare(stmtPtr, nativeSqlStr, nativeSqlLen)) {
	    TransferMysqlStmtError(interp, stmtPtr);
	    mysql_stmt_close(stmtPtr);
	    stmtPtr = NULL;
	}
    }
................................................................................
    if (Tcl_ListObjGetElements(interp, tokens, &tokenc, &tokenv) != TCL_OK) {
	goto freeTokens;
    }
    nativeSql = Tcl_NewObj();
    Tcl_IncrRefCount(nativeSql);
    for (i = 0; i < tokenc; ++i) {
	tokenStr = Tcl_GetStringFromObj(tokenv[i], &tokenLen);

	switch (tokenStr[0]) {
	case '$':
	case ':':
	case '@':
	    Tcl_AppendToObj(nativeSql, "?", 1);
	    Tcl_ListObjAppendElement(NULL, sdata->subVars,
				     Tcl_NewStringObj(tokenStr+1, tokenLen-1));
	    break;

	case ';':
	    Tcl_SetObjResult(interp,
			     Tcl_NewStringObj("tdbc::mysql"
					      " does not support semicolons "
					      "in statements", -1));
	    goto freeNativeSql;
	    break;

	default:
	    Tcl_AppendToObj(nativeSql, tokenStr, tokenLen);
	    break;

	}
    }
................................................................................
    Tcl_ListObjLength(NULL, sdata->subVars, &nParams);
    for (i = 0; i < nParams; ++i) {
	paramDesc = Tcl_NewObj();
	Tcl_ListObjIndex(NULL, sdata->subVars, i, &paramName);
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_NAME], paramName);
	switch (sdata->params[i].flags & (PARAM_IN | PARAM_OUT)) {
	case PARAM_IN:
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_DIRECTION],
			   literals[LIT_IN]);
	    break;
	case PARAM_OUT:
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_DIRECTION],
			   literals[LIT_OUT]);
	    break;
	case PARAM_IN | PARAM_OUT:
	    Tcl_DictObjPut(NULL, paramDesc, literals[LIT_DIRECTION],
			   literals[LIT_INOUT]);
	    break;
	default:
	    break;
	}
	typeHashEntry =
	    Tcl_FindHashEntry(&(pidata->typeNumHash),
................................................................................
	}
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_PRECISION],
		       Tcl_NewIntObj(sdata->params[i].precision));
	Tcl_DictObjPut(NULL, paramDesc, literals[LIT_SCALE],
		       Tcl_NewIntObj(sdata->params[i].scale));
	Tcl_DictObjPut(NULL, retVal, paramName, paramDesc);
    }

    Tcl_SetObjResult(interp, retVal);
    return TCL_OK;
}
 
/*
 *-----------------------------------------------------------------------------
 *
................................................................................
    int i;

    /* Check parameters */

    if (objc < 4) {
	goto wrongNumArgs;
    }

    i = 3;
    if (Tcl_GetIndexFromObjStruct(interp, objv[i], directions,
				  sizeof(directions[0]), "direction",
				  TCL_EXACT, &direction) != TCL_OK) {
	direction = PARAM_IN;
	Tcl_ResetResult(interp);
    } else {
	++i;
    }
................................................................................
    Tcl_Obj* paramValObj;	/* Value of the current parameter */
    const char* paramValStr;	/* String value of the current parameter */
    char* bufPtr;		/* Pointer to the parameter buffer */
    int len;			/* Length of a bound parameter */
    int nColumns;		/* Number of columns in the result set */
    MYSQL_FIELD* fields = NULL;	/* Description of columns of the result set */
    MYSQL_BIND* resultBindings;	/* Bindings of the columns of the result set */
    unsigned long* resultLengths;
				/* Lengths of the columns of the result set */
    int i;

    /* Check parameter count */

    if (objc != skip+1 && objc != skip+2) {
	Tcl_WrongNumArgs(interp, skip, objv, "statement ?dictionary?");
................................................................................
	Tcl_AppendResult(interp, Tcl_GetString(objv[skip]),
			 " does not refer to a MySQL statement", NULL);
	return TCL_ERROR;
    }
    Tcl_ListObjLength(NULL, sdata->columnNames, &nColumns);
    cdata = sdata->cdata;

    /*
     * If there is no transaction in progress, turn on auto-commit so that
     * this statement will execute directly.
     */

    if ((cdata->flags & (CONN_FLAG_IN_XCN | CONN_FLAG_AUTOCOMMIT)) == 0) {
	if (mysql_autocommit(cdata->mysqlPtr, 1)) {
	    TransferMysqlError(interp, cdata->mysqlPtr);
................................................................................
			       paramNameObj, &paramValObj) != TCL_OK) {
		return TCL_ERROR;
	    }
	} else {

	    /* Param from a variable */

	    paramValObj = Tcl_GetVar2Ex(interp, paramName, NULL,
					TCL_LEAVE_ERR_MSG);
	}

	/*
	 * At this point, paramValObj contains the parameter to bind.
	 * Convert the parameters to the appropriate data types for
	 * MySQL's prepared statement interface, and bind them.
	 */

	if (paramValObj != NULL) {
	    switch (sdata->params[nBound].dataType & 0xffff) {
................................................................................
					   MYSQL_TYPE_BLOB);
		    paramValStr = (char*)
			Tcl_GetByteArrayFromObj(paramValObj, &len);
		} else {
		    MysqlBindSetBufferType(rdata->paramBindings, nBound,
					   MYSQL_TYPE_STRING);
		    paramValStr = Tcl_GetStringFromObj(paramValObj, &len);
		}
		bufPtr = MysqlBindAllocBuffer(rdata->paramBindings, nBound,
					      len+1);
		memcpy(bufPtr, paramValStr, len);
		rdata->paramLengths[nBound] = len;
		MysqlBindSetLength(rdata->paramBindings, nBound,
				   &(rdata->paramLengths[nBound]));
		break;

	    }
	} else {
	    MysqlBindSetBufferType(rdata->paramBindings, nBound,
				   MYSQL_TYPE_NULL);
	}
    }

    /* Execute the statement */

    /*
     * It is tempting to conserve client memory here by omitting
     * the call to 'mysql_stmt_store_result', but doing so causes
     * 'calls out of sync' errors when attempting to prepare a
     * statement while a result set is open. Certain of these errors
     * can, in turn, be avoided by using mysql_stmt_set_attr
     * and turning on "CURSOR_MODE_READONLY", but that, in turn
     * causes the server summarily to disconnect the client in
................................................................................
				/* Per interpreter data */
    Tcl_Obj** literals = pidata->literals;
				/* Literal pool */

    int nColumns = 0;		/* Number of columns in the result set */
    Tcl_Obj* colName;		/* Name of the current column */
    Tcl_Obj* resultRow;		/* Row of the result set under construction */

    Tcl_Obj* colObj;		/* Column obtained from the row */
    int status = TCL_ERROR;	/* Status return from this command */
    MYSQL_FIELD* fields;	/* Fields of the result set */
    MYSQL_BIND* resultBindings = rdata->resultBindings;
				/* Descriptions of the results */
    unsigned long* resultLengths = rdata->resultLengths;
				/* String lengths of the results */
................................................................................
	MYSQL_FIELD* field = MysqlFieldIndex(fields, i);
	colObj = NULL;
	if (!resultNulls[i]) {
	    if (resultLengths[i]
		> MysqlBindGetBufferLength(resultBindings, i)) {
		MysqlBindFreeBuffer(resultBindings, i);
		MysqlBindAllocBuffer(resultBindings, i, resultLengths[i] + 1);
		if (mysql_stmt_fetch_column(rdata->stmtPtr,
					    MysqlBindIndex(resultBindings, i),
					    i, 0)) {
		    goto cleanup;
		}
	    }
	    bufPtr = MysqlBindGetBuffer(resultBindings, i);
	    switch (MysqlBindGetBufferType(resultBindings, i)) {
................................................................................

    /* Provide the current package */

    if (Tcl_PkgProvide(interp, "tdbc::mysql", PACKAGE_VERSION) == TCL_ERROR) {
	return TCL_ERROR;
    }

    /*
     * Create per-interpreter data for the package
     */

    pidata = (PerInterpData*) ckalloc(sizeof(PerInterpData));
    pidata->refCount = 1;
    for (i = 0; i < LIT__END; ++i) {
	pidata->literals[i] = Tcl_NewStringObj(LiteralValues[i], -1);
	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].num),
				&new);
	Tcl_Obj* nameObj = Tcl_NewStringObj(dataTypes[i].name, -1);
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(entry, (ClientData) nameObj);
    }

    /*
     * Find the connection class, and attach an 'init' method to it.
     */

    nameObj = Tcl_NewStringObj("::tdbc::mysql::connection", -1);
    Tcl_IncrRefCount(nameObj);
    if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
	Tcl_DecrRefCount(nameObj);

Changes to library/tdbcmysql.tcl.

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	if {$varName eq {}} {
	    my prepare "CALL $rest"
	} else {
	    my prepare \\{:$varName=$rest\\}
	}
    }

    # The 'init', 'begintransaction', 'commit, 'rollback', 'tables' 
    # 'NeedCollationInfo', 'SetCollationInfo', and 'Columns' methods 
    # are implemented in C.

    # The 'BuildForeignKeysStatements' method builds a SQL statement to
    # retrieve the foreign keys from a database. (It executes once the
    # first time the 'foreignKeys' method is executed, and retains the
    # prepared statements for reuse.)  It is slightly nonstandard because
    # MYSQL doesn't name the PRIMARY constraints uniquely.
................................................................................
    #     -- Executes the statement against the database, optionally providing
    #        a dictionary of substituted parameters (default is to get params
    #        from variables in the caller's scope).
    # columns
    #     -- Returns a list of the names of the columns in the result.
    # nextdict
    #     -- Stores the next row of the result set in the given variable in
    #        the caller's scope as a dictionary whose keys are 
    #        column names and whose values are column values, or else
    #        as a list of cells.
    # nextlist
    #     -- Stores the next row of the result set in the given variable in
    #        the caller's scope as a list of cells.
    # rowcount
    #     -- Returns a count of rows affected by the statement, or -1
    #        if the count of rows has not been determined.

}






|
|







 







|










74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	if {$varName eq {}} {
	    my prepare "CALL $rest"
	} else {
	    my prepare \\{:$varName=$rest\\}
	}
    }

    # The 'init', 'begintransaction', 'commit, 'rollback', 'tables'
    # 'NeedCollationInfo', 'SetCollationInfo', and 'Columns' methods
    # are implemented in C.

    # The 'BuildForeignKeysStatements' method builds a SQL statement to
    # retrieve the foreign keys from a database. (It executes once the
    # first time the 'foreignKeys' method is executed, and retains the
    # prepared statements for reuse.)  It is slightly nonstandard because
    # MYSQL doesn't name the PRIMARY constraints uniquely.
................................................................................
    #     -- Executes the statement against the database, optionally providing
    #        a dictionary of substituted parameters (default is to get params
    #        from variables in the caller's scope).
    # columns
    #     -- Returns a list of the names of the columns in the result.
    # nextdict
    #     -- Stores the next row of the result set in the given variable in
    #        the caller's scope as a dictionary whose keys are
    #        column names and whose values are column values, or else
    #        as a list of cells.
    # nextlist
    #     -- Stores the next row of the result set in the given variable in
    #        the caller's scope as a list of cells.
    # rowcount
    #     -- Returns a count of rows affected by the statement, or -1
    #        if the count of rows has not been determined.

}

Changes to license.terms.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal 
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license. 






|







|
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.

Changes to tests/all.tcl.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#
# This file contains a top-level script to run all of the Tcl
# tests.  Execute it by invoking "source all.test" when running tcltest
# in this directory.
#
# Copyright (c) 1998-2000 by Scriptics Corporation.
# All rights reserved.
# 
# RCS: @(#) $Id: all.tcl,v 1.4 2004/07/04 22:04:20 patthoyts Exp $

package require Tcl 8.6
package require tcltest 2.2
::tcltest::configure \
    -testdir [file dirname [file normalize [info script]]] \
    {*}$argv
::tcltest::runAllTests
rename exit {}






|









2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#
# This file contains a top-level script to run all of the Tcl
# tests.  Execute it by invoking "source all.test" when running tcltest
# in this directory.
#
# Copyright (c) 1998-2000 by Scriptics Corporation.
# All rights reserved.
#
# RCS: @(#) $Id: all.tcl,v 1.4 2004/07/04 22:04:20 patthoyts Exp $

package require Tcl 8.6
package require tcltest 2.2
::tcltest::configure \
    -testdir [file dirname [file normalize [info script]]] \
    {*}$argv
::tcltest::runAllTests
rename exit {}

Changes to tests/tdbcmysql.test.

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
...
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
....
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
....
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
....
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
....
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
....
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
....
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
....
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
....
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
....
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
....
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
....
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
....
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
....
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
    }
    -match glob
    -result {1 {Unknown MySQL server host*} {TDBC GENERAL_ERROR HY000 MYSQL *}}
}

#------------------------------------------------------------------------------
#
# Bail out if the user hasn't set TDBCMYSQL_TEST_DB 

if {![info exists env(TDBCMYSQL_TEST_DB)]} {
    puts "Not performing functional testing of tdbc::mysql because\
          env(TDBCMYSQL_TEST_DB) is not set."
    cleanupTests
    return
}
................................................................................
    -returnCodes error
    -match glob
    -result {wrong # args*}
}

test tdbc::mysql-2.2 {don't make a statement without a connection} {*}{
    -body {
	tdbc::mysql::statement create stmt rubbish moreRubbish 
    }
    -returnCodes error
    -result {rubbish does not refer to an object}
}

test tdbc::mysql-2.3 {don't make a statement without a connection} {*}{
    -body {
	tdbc::mysql::statement create stmt oo::class moreRubbish 
    }
    -returnCodes error
    -result {oo::class does not refer to a MySQL connection}
}

test tdbc::mysql-2.4 {semicolons in statements} {*}{
    -body {
................................................................................
    -cleanup {
	rename $stmt {}
    }
    -returnCodes error
    -match glob
    -result {wrong # args*}
}
    
test tdbc::mysql-5.3 {paramtype - bad type} {*}{
    -setup {
	set stmt [::db prepare {
	    INSERT INTO people(idnum, name, info) values(:idnum, :name, 0)
	}]
    }
    -body {
................................................................................
    }
    -cleanup {
	rename $rs {}
	rename $stmt {}
    }
    -result {fred wilma pebbles barney betty bam-bam}
}
    
test tdbc::mysql-8.2 {nextrow - as lists} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people ORDER BY idnum
	}]
	set rs [$stmt execute]
    }
................................................................................
	list [$rs nextrow -as lists -- row] $row [$rs nextrow -as lists -- row]
    }
    -cleanup {
	$stmt close
    }
    -result {1 {1 fred {}} 0}
}
	
test tdbc::mysql-9.1 {rs foreach var script} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}]
	set rs [$stmt execute]
    }
................................................................................
	$rs foreach row
    }
    -cleanup {
	$rs close
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*} 
    -match glob
}

test tdbc::mysql-9.38 {stmt foreach - too few args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people
................................................................................
    -body {
	$stmt foreach row
    }
    -cleanup {
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*} 
    -match glob
}

test tdbc::mysql-9.39 {db foreach - too few args} {*}{
    -body {
	db foreach row {
	    SELECT idnum, name FROM people
	}
    }
    -returnCodes error
    -result {wrong # args*} 
    -match glob
}

test tdbc::mysql-9.40 {rs foreach - too many args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people
	}]
	set rs [$stmt execute]
    }
    -body {
	$rs foreach row do something 
    }
    -cleanup {
	$rs close
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*} 
    -match glob
}

test tdbc::mysql-9.41 {stmt foreach - too many args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people
................................................................................
    -body {
	$stmt foreach row do something else
    }
    -cleanup {
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*} 
    -match glob
}

test tdbc::mysql-9.42 {db foreach - too many args} {*}{
    -body {
	db foreach row {
	    SELECT idnum, name FROM people
	} {} do something
    }
    -returnCodes error
    -result {wrong # args*} 
    -match glob
}

test tdbc::mysql-10.1 {allrows - no args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
................................................................................
test tdbc::mysql-10.6 {allrows --} {*}{
    -body {
	db allrows -- {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}
    }
    -result {{idnum 4 name barney} {idnum 5 name betty} {idnum 6 name bam-bam}}
}    

test tdbc::mysql-10.7 {allrows -as lists} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}]
	set rs [$stmt execute]
................................................................................
    -body {
	db allrows -as lists {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}
    }
    -result {{4 barney} {5 betty} {6 bam-bam}}
}
    
test tdbc::mysql-10.10 {allrows -as lists --} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}]
	set rs [$stmt execute]
    }
................................................................................
    -body {
	$stmt allrows {} rubbish
    }
    -cleanup {
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*} 
    -match glob
}

test tdbc::mysql-10.21 {bad -as} {*}{
    -body {
	db allrows -as trash {
	    SELECT idnum, name FROM people
................................................................................
# and [db foreignkeys] depends on it.

set version unknown
db foreach -as lists -- row {SELECT version()} {
    set version [lindex $row 0]
}
tcltest::testConstraint mysqlAtLeast5116 \
    [expr {[regexp {^\d+\.\d+(?:\.\d+)?} $version components] 
	   && [package vcompare $components 5.1.16] >= 0}]

catch {
    set stmt [db prepare {
	INSERT INTO people(idnum, name, info) VALUES(:idnum, :name, NULL)
    }]
    $stmt paramtype idnum integer
................................................................................
    -result {}
}

test tdbc::mysql-16.3 {enumerate database tables} {*}{
    -body {
	set dict [::db tables]
	list [dict exists $dict people] [dict exists $dict property]
    } 
    -result {1 0}
}

test tdbc::mysql-16.4 {enumerate database tables} {*}{
    -body {
	set dict [::db tables p%]
	list [dict exists $dict people] [dict exists $dict property]
    } 
    -result {1 0}
}

test tdbc::mysql-17.1 {database columns - wrong # args} {*}{
    -body {
	set dict [::db columns people % rubbish]
    }
................................................................................
    }
    -result {idnum integer 11 0 0 info integer 11 0 1}
}

test tdbc::mysql-18.1 {$statement params - excess arg} {*}{
    -setup {
	set s [::db prepare {
	    SELECT name FROM people 
	    WHERE name LIKE :pattern
	    AND idnum >= :minid
	}]
	$s paramtype minid numeric 10 0
	$s paramtype pattern varchar 40
    }
    -body {
	$s params excess
    } 
    -cleanup {
	rename $s {}
    }
    -returnCodes error
    -match glob
    -result {wrong # args*}
}

test tdbc::mysql-18.2 {$statement params - no params} {*}{
    -setup {
	set s [::db prepare {
	    SELECT name FROM people 
	}]
    }
    -body {
	$s params
    } 
    -cleanup {
	rename $s {}
    }
    -result {}
}

test tdbc::mysql-18.3 {$statement params - try a few data types} {*}{
    -setup {
	set s [::db prepare {
	    SELECT name FROM people 
	    WHERE name LIKE :pattern
	    AND idnum >= :minid
	}]
	$s paramtype minid decimal 10 0
	$s paramtype pattern varchar 40
    }
    -body {
................................................................................
	    [dict get $d minid direction] \
	    [dict get $d minid type] \
	    [dict get $d minid precision] \
	    [dict get $d minid scale] \
	    [dict get $d pattern direction] \
	    [dict get $d pattern type] \
	    [dict get $d pattern precision]
    } 
    -cleanup {
	rename $s {}
    }
    -result {in decimal 10 0 in varchar 40}
}

test tdbc::mysql-19.1 {$connection configure - no args} \
................................................................................
	$stmt paramtype xlongb1 longblob
	$stmt paramtype xtext1 text
	$stmt paramtype xblob1 blob
	$stmt paramtype xvarb1 varbinary
	$stmt paramtype xvarc1 varchar
	$stmt paramtype xbin1 binary 20
	$stmt paramtype xchar1 char 20
    } 
    -body {
	set trouble {}
	set xtiny1 0x14
	set xsmall1 0x3039
	set xint1 0xbc614e
	set xfloat1 1.125
	set xdouble1 1.125
................................................................................
	db allrows {DROP TABLE bintest}
    }
}

test tdbc::mysql-22.1 {duplicate column name} {*}{
    -body {
	set stmt [::db prepare {
	    SELECT a.idnum, b.idnum 
	    FROM people a, people b
	    WHERE a.name = 'hud rockstone' 
	    AND b.info = a.info
	}]
	set rs [$stmt execute]
	$rs columns
    }
    -result {idnum idnum#2}
    -cleanup {
................................................................................
test tdbc::mysql-23.1 {Primary keys - no arg} {*}{
    -body {
	::db primarykeys
    }
    -returnCodes error
    -match glob
    -result {wrong # args*}
} 
test tdbc::mysql-23.2 {Primary keys - no primary key} {*}{
    -body {
	::db primarykeys d
    }
    -result {}
}
test tdbc::mysql-23.3 {Primary keys - simple primary key} {*}{






|







 







|







|







 







|







 







|







 







|







 







|







 







|










|











|






|







 







|










|







 







|







 







|







 







|







 







|







 







|







|







 







|








|











|




|









|







 







|







 







|







 







|

|







 







|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
...
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
....
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
....
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
....
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
....
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
....
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
....
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
....
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
....
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
....
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
....
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
....
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
....
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
....
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
    }
    -match glob
    -result {1 {Unknown MySQL server host*} {TDBC GENERAL_ERROR HY000 MYSQL *}}
}

#------------------------------------------------------------------------------
#
# Bail out if the user hasn't set TDBCMYSQL_TEST_DB

if {![info exists env(TDBCMYSQL_TEST_DB)]} {
    puts "Not performing functional testing of tdbc::mysql because\
          env(TDBCMYSQL_TEST_DB) is not set."
    cleanupTests
    return
}
................................................................................
    -returnCodes error
    -match glob
    -result {wrong # args*}
}

test tdbc::mysql-2.2 {don't make a statement without a connection} {*}{
    -body {
	tdbc::mysql::statement create stmt rubbish moreRubbish
    }
    -returnCodes error
    -result {rubbish does not refer to an object}
}

test tdbc::mysql-2.3 {don't make a statement without a connection} {*}{
    -body {
	tdbc::mysql::statement create stmt oo::class moreRubbish
    }
    -returnCodes error
    -result {oo::class does not refer to a MySQL connection}
}

test tdbc::mysql-2.4 {semicolons in statements} {*}{
    -body {
................................................................................
    -cleanup {
	rename $stmt {}
    }
    -returnCodes error
    -match glob
    -result {wrong # args*}
}

test tdbc::mysql-5.3 {paramtype - bad type} {*}{
    -setup {
	set stmt [::db prepare {
	    INSERT INTO people(idnum, name, info) values(:idnum, :name, 0)
	}]
    }
    -body {
................................................................................
    }
    -cleanup {
	rename $rs {}
	rename $stmt {}
    }
    -result {fred wilma pebbles barney betty bam-bam}
}

test tdbc::mysql-8.2 {nextrow - as lists} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people ORDER BY idnum
	}]
	set rs [$stmt execute]
    }
................................................................................
	list [$rs nextrow -as lists -- row] $row [$rs nextrow -as lists -- row]
    }
    -cleanup {
	$stmt close
    }
    -result {1 {1 fred {}} 0}
}

test tdbc::mysql-9.1 {rs foreach var script} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}]
	set rs [$stmt execute]
    }
................................................................................
	$rs foreach row
    }
    -cleanup {
	$rs close
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*}
    -match glob
}

test tdbc::mysql-9.38 {stmt foreach - too few args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people
................................................................................
    -body {
	$stmt foreach row
    }
    -cleanup {
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*}
    -match glob
}

test tdbc::mysql-9.39 {db foreach - too few args} {*}{
    -body {
	db foreach row {
	    SELECT idnum, name FROM people
	}
    }
    -returnCodes error
    -result {wrong # args*}
    -match glob
}

test tdbc::mysql-9.40 {rs foreach - too many args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people
	}]
	set rs [$stmt execute]
    }
    -body {
	$rs foreach row do something
    }
    -cleanup {
	$rs close
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*}
    -match glob
}

test tdbc::mysql-9.41 {stmt foreach - too many args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people
................................................................................
    -body {
	$stmt foreach row do something else
    }
    -cleanup {
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*}
    -match glob
}

test tdbc::mysql-9.42 {db foreach - too many args} {*}{
    -body {
	db foreach row {
	    SELECT idnum, name FROM people
	} {} do something
    }
    -returnCodes error
    -result {wrong # args*}
    -match glob
}

test tdbc::mysql-10.1 {allrows - no args} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
................................................................................
test tdbc::mysql-10.6 {allrows --} {*}{
    -body {
	db allrows -- {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}
    }
    -result {{idnum 4 name barney} {idnum 5 name betty} {idnum 6 name bam-bam}}
}

test tdbc::mysql-10.7 {allrows -as lists} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}]
	set rs [$stmt execute]
................................................................................
    -body {
	db allrows -as lists {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}
    }
    -result {{4 barney} {5 betty} {6 bam-bam}}
}

test tdbc::mysql-10.10 {allrows -as lists --} {*}{
    -setup {
	set stmt [::db prepare {
	    SELECT idnum, name FROM people WHERE name LIKE 'b%'
	}]
	set rs [$stmt execute]
    }
................................................................................
    -body {
	$stmt allrows {} rubbish
    }
    -cleanup {
	$stmt close
    }
    -returnCodes error
    -result {wrong # args*}
    -match glob
}

test tdbc::mysql-10.21 {bad -as} {*}{
    -body {
	db allrows -as trash {
	    SELECT idnum, name FROM people
................................................................................
# and [db foreignkeys] depends on it.

set version unknown
db foreach -as lists -- row {SELECT version()} {
    set version [lindex $row 0]
}
tcltest::testConstraint mysqlAtLeast5116 \
    [expr {[regexp {^\d+\.\d+(?:\.\d+)?} $version components]
	   && [package vcompare $components 5.1.16] >= 0}]

catch {
    set stmt [db prepare {
	INSERT INTO people(idnum, name, info) VALUES(:idnum, :name, NULL)
    }]
    $stmt paramtype idnum integer
................................................................................
    -result {}
}

test tdbc::mysql-16.3 {enumerate database tables} {*}{
    -body {
	set dict [::db tables]
	list [dict exists $dict people] [dict exists $dict property]
    }
    -result {1 0}
}

test tdbc::mysql-16.4 {enumerate database tables} {*}{
    -body {
	set dict [::db tables p%]
	list [dict exists $dict people] [dict exists $dict property]
    }
    -result {1 0}
}

test tdbc::mysql-17.1 {database columns - wrong # args} {*}{
    -body {
	set dict [::db columns people % rubbish]
    }
................................................................................
    }
    -result {idnum integer 11 0 0 info integer 11 0 1}
}

test tdbc::mysql-18.1 {$statement params - excess arg} {*}{
    -setup {
	set s [::db prepare {
	    SELECT name FROM people
	    WHERE name LIKE :pattern
	    AND idnum >= :minid
	}]
	$s paramtype minid numeric 10 0
	$s paramtype pattern varchar 40
    }
    -body {
	$s params excess
    }
    -cleanup {
	rename $s {}
    }
    -returnCodes error
    -match glob
    -result {wrong # args*}
}

test tdbc::mysql-18.2 {$statement params - no params} {*}{
    -setup {
	set s [::db prepare {
	    SELECT name FROM people
	}]
    }
    -body {
	$s params
    }
    -cleanup {
	rename $s {}
    }
    -result {}
}

test tdbc::mysql-18.3 {$statement params - try a few data types} {*}{
    -setup {
	set s [::db prepare {
	    SELECT name FROM people
	    WHERE name LIKE :pattern
	    AND idnum >= :minid
	}]
	$s paramtype minid decimal 10 0
	$s paramtype pattern varchar 40
    }
    -body {
................................................................................
	    [dict get $d minid direction] \
	    [dict get $d minid type] \
	    [dict get $d minid precision] \
	    [dict get $d minid scale] \
	    [dict get $d pattern direction] \
	    [dict get $d pattern type] \
	    [dict get $d pattern precision]
    }
    -cleanup {
	rename $s {}
    }
    -result {in decimal 10 0 in varchar 40}
}

test tdbc::mysql-19.1 {$connection configure - no args} \
................................................................................
	$stmt paramtype xlongb1 longblob
	$stmt paramtype xtext1 text
	$stmt paramtype xblob1 blob
	$stmt paramtype xvarb1 varbinary
	$stmt paramtype xvarc1 varchar
	$stmt paramtype xbin1 binary 20
	$stmt paramtype xchar1 char 20
    }
    -body {
	set trouble {}
	set xtiny1 0x14
	set xsmall1 0x3039
	set xint1 0xbc614e
	set xfloat1 1.125
	set xdouble1 1.125
................................................................................
	db allrows {DROP TABLE bintest}
    }
}

test tdbc::mysql-22.1 {duplicate column name} {*}{
    -body {
	set stmt [::db prepare {
	    SELECT a.idnum, b.idnum
	    FROM people a, people b
	    WHERE a.name = 'hud rockstone'
	    AND b.info = a.info
	}]
	set rs [$stmt execute]
	$rs columns
    }
    -result {idnum idnum#2}
    -cleanup {
................................................................................
test tdbc::mysql-23.1 {Primary keys - no arg} {*}{
    -body {
	::db primarykeys
    }
    -returnCodes error
    -match glob
    -result {wrong # args*}
}
test tdbc::mysql-23.2 {Primary keys - no primary key} {*}{
    -body {
	::db primarykeys d
    }
    -result {}
}
test tdbc::mysql-23.3 {Primary keys - simple primary key} {*}{

Changes to win/makefile.vc.

1
2
3
4
5
6
7
8
9
10
11
12
13
#------------------------------------------------------------- -*- makefile -*-
# makefile.vc --
#
#	Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)
#
# This makefile is based upon the Tcl 8.6 Makefile.vc and modified to 
# make it suitable as a general package makefile. Look for the word EDIT
# which marks sections that may need modification. As a minumum you will
# need to change the PROJECT, DOTVERSION and DLLOBJS variables to values
# relevant to your package.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.




|







1
2
3
4
5
6
7
8
9
10
11
12
13
#------------------------------------------------------------- -*- makefile -*-
# makefile.vc --
#
#	Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)
#
# This makefile is based upon the Tcl 8.6 Makefile.vc and modified to
# make it suitable as a general package makefile. Look for the word EDIT
# which marks sections that may need modification. As a minumum you will
# need to change the PROJECT, DOTVERSION and DLLOBJS variables to values
# relevant to your package.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.